Modular Package Architecture
Intent
Enable large-scale Salesforce development through independent, composable packages that can be developed, tested, and deployed in isolation while maintaining clear boundaries and contracts between components.
Core Principles
1. Package Layering Strategy
The architecture follows a strict layered approach where dependencies flow in one direction:
Environment-Specific → Access Management → Feature Packages → Domain Packages → Core → Common/Frameworks2. Package Types and Responsibilities
Foundation Layer
common: Shared frameworks (fflib, logger) with no business logic
core-unpackaged: Base metadata that cannot be packaged
Core Layer
core: Central business services, selectors, and domain classes
Provides interfaces that other packages implement or consume
Contains the main Application class for dependency injection
Domain Packages
Feature-complete vertical slices (e.g.,
revenue,lead-management)Self-contained with their own Application_XX class
Depend only on core and common
Infrastructure Packages
env-specific-alias-pre: Environment-specific configuration
access-management: Security and permissions
ui: User interface components
Implementation Pattern
Package Application Class
Each package defines its own Application class following this pattern:
Service Interface Pattern
Services expose functionality through interfaces:
Cross-Package Communication
Packages communicate through:
Service Interfaces - Synchronous calls through defined contracts
Platform Events - Asynchronous, loosely coupled communication
Custom Metadata - Configuration-driven behavior
Package Configuration
sfdx-project.json Structure
Environment-Specific Configuration
Deployment Strategy
Release Configuration
Package Deployment Order
Environment-specific configuration (
aliasfy: true)Foundation packages (common, frameworks)
Core business packages
Feature packages
UI packages (
alwaysDeploy: true)Access management packages
Benefits
Development Benefits
Parallel Development: Teams work on packages independently
Clear Ownership: Each package has defined boundaries
Faster CI/CD: Deploy only changed packages
Isolated Testing: Test packages in isolation with mocks
Architectural Benefits
Loose Coupling: Packages communicate through interfaces
High Cohesion: Related functionality grouped together
Reusability: Packages can be shared across orgs
Maintainability: Changes isolated to specific packages
Anti-Patterns to Avoid
1. Circular Dependencies
2. Package Sprawl
3. Hidden Coupling
Package Sizing Guidelines
When to Create a New Package
Distinct business domain (10+ related objects)
Different deployment cadence
Separate team ownership
Reusable across multiple orgs
When to Keep in Existing Package
Tightly coupled functionality
Shared transaction boundaries
< 5 objects or 20 classes
Same deployment lifecycle
Testing Strategy
Unit Testing
Integration Testing
Deploy packages to scratch org in correct order
Run integration test suite across packages
Validate cross-package platform events
Migration Path
From Monolithic to Modular
Identify Boundaries: Map existing code to domains
Extract Interfaces: Define service contracts
Create Package Structure: Set up package directories
Move Code Incrementally: One domain at a time
Update Dependencies: Adjust sfdx-project.json
Test Thoroughly: Ensure no regression
Production Implementation Patterns
Successful implementations of this architecture demonstrate:
Dozens of packages managed independently in production systems
Clear separation between foundation, core, domain, and UI layers
Environment-specific configuration packages using
aliasfy: truefor environment-based deploymentPackage-specific Application classes following the Application_XX pattern for each domain
Successful scaling to large development teams working in parallel without conflicts
Last updated
Was this helpful?