Platform Capabilities & Constraints
Salesforce architectural decisions must account for governor limits, shared resource constraints, and platform boundaries. Solutions that work within these constraints scale predictably; those that don’t hit limits in production.
Multi-Tenant Architecture
All customers (tenants) share the same compute, storage, and network resources. Governor limits exist to prevent any single tenant from monopolizing those shared resources.
The kernel reads tenant-specific metadata from the Universal Data Dictionary (UDD) at runtime to dynamically construct each tenant’s application, business logic, and APIs. Every database query is automatically scoped by OrgID, which ensures strict tenant isolation at the data layer. Custom objects, fields, triggers, and validation rules are all stored as metadata, not compiled code. This is how Salesforce deploys platform upgrades without affecting tenant customizations.
Multi-Tenancy Implications
| Aspect | Implication for Architects |
|---|---|
| Shared database | Cannot run arbitrary SQL; must use SOQL/SOSL within limits |
| Shared compute | CPU time limits per transaction; no long-running processes |
| Shared network | API call limits per 24-hour period; callout time limits |
| No raw file system | Cannot write to disk; must use ContentDocument or external storage |
| No custom OS processes | Cannot run background daemons; must use platform async frameworks |
| Metadata-driven | Custom objects, fields, and configuration stored as metadata; schema changes are API calls |
| Automatic upgrades | Three releases per year; cannot defer; must test in advance |
The architect’s mindset
Multi-tenancy is not a limitation to work around. It is the foundation that provides automatic scaling, zero-downtime upgrades, and enterprise security at commodity pricing. Go off-platform only when the platform genuinely cannot serve the requirement.
Governor Limits Reference
Per-Transaction Limits (Synchronous)
| Resource | Limit | Notes |
|---|---|---|
| SOQL queries | 100 | Per Apex transaction |
| Records retrieved (SOQL) | 50,000 | Per transaction |
| SOSL searches | 20 | Per transaction |
| Records retrieved (SOSL) | 2,000 | Per transaction |
| DML statements | 150 | Per transaction |
| Records processed (DML) | 10,000 | Per transaction |
| Callouts | 100 | Per transaction |
| Callout timeout | 120 seconds per callout | Max 120s per individual callout (configurable via HttpRequest.setTimeout, default 10s); 120s total across all callouts in a transaction |
| CPU time | 10,000 ms | Per transaction |
| Heap size | 6 MB | Per synchronous transaction |
| Future calls | 50 | Per transaction |
| Queueable jobs | 50 | Per transaction |
| Email invocations | 10 | Per transaction |
| Push notification calls | 10 | Per transaction |
| EventBus.publish | 150 | Per transaction |
Per-Transaction Limits (Asynchronous)
| Resource | Limit | Notes |
|---|---|---|
| SOQL queries | 200 | Double the synchronous limit |
| Records retrieved (SOQL) | 50,000 | Same as synchronous |
| CPU time | 60,000 ms | 6x the synchronous limit |
| Heap size | 12 MB | Double the synchronous limit |
Per-24-Hour Limits
| Resource | Limit | Notes |
|---|---|---|
| API calls | 100,000+ | Base + per-user allocation (varies by edition) |
| Async Apex executions | 250,000 or 200 x licenses | Whichever is greater |
| Batch Apex jobs | 100 queued or active | At any one time |
| Future calls | 250,000 or 200 x licenses | Whichever is greater |
| Platform Events published | Based on entitlement | Varies; default 100K/day for most editions |
| Outbound emails | 5,000 external recipients/day (single + mass combined) | Per-blast limit: 500 (EE), 1,000 (UE/PE). Daily cap shared across single and mass email |
| Scheduled Apex jobs | 100 | Concurrent scheduled jobs |
Data and Storage Limits
| Resource | Limit | Notes |
|---|---|---|
| Custom objects | 200-2,000 | Varies by edition |
| Custom fields per object | Up to 500 | Varies by edition and field type - consult ‘Custom Fields Allowed Per Object’ help article for precise limits |
| Data storage | 10 GB base + per-user | See Org Strategy for edition details |
| File storage | 10 GB base + per-user | See Document Management |
| Record size | ~8 KB per record | Aggregate of all field values |
| SOQL query length | 100,000 characters | Including WHERE, ORDER BY |
| Formula field size | 5,000 characters compiled | Complex formulas may exceed this |
Synchronous vs Asynchronous Limits - Visual Comparison
The async escalation path
When a synchronous transaction hits governor limits, the first response should be to evaluate async processing. Async gives 2x SOQL, 6x CPU time, and 2x heap. If async limits are still insufficient, that is the signal to move off-platform. This escalation path - sync, then async, then off-platform - is a pattern CTA judges expect to see.
Limits you will hit
The limits CTAs most frequently encounter in real-world scenarios: (1) 100 SOQL per synchronous transaction - poor code design or AppExchange packages that query in loops, (2) 10,000 DML records - bulk data operations, (3) API calls per 24 hours - integration-heavy architectures, (4) CPU time - complex Flow automation chains.
On-Platform vs Off-Platform Decision Framework
A core system architecture question: should this run on the Salesforce platform or somewhere else?
Decision Matrix
| Factor | On-Platform | Off-Platform |
|---|---|---|
| Data ownership | Data is primarily Salesforce data | Data lives in external systems |
| User context | Users are already in Salesforce | Users are not Salesforce users |
| Transaction complexity | Within governor limits | Exceeds governor limits |
| Processing time | Under 10 seconds (sync) or 60 seconds (async) | Long-running processes (minutes to hours) |
| Custom UI | Lightning components are sufficient | Complex UI beyond Lightning capabilities |
| Device integration | Standard browser/mobile | IoT, sensors, specialized hardware |
| Compute requirements | Light computation | Heavy computation, ML model training |
| Real-time streaming | Platform Events (limited) | Kafka, Kinesis, or custom streaming |
| Data volume | Under LDV thresholds | Billions of records, data lake/warehouse |
| Regulatory | Standard compliance | Specialized compliance (PCI DSS, HIPAA BAA) |
On-Platform vs Off-Platform Architecture
Decision Flowchart
Asynchronous Apex Patterns
Async patterns provide higher limits and background processing when synchronous execution hits governor limits.
Async Pattern Comparison
| Pattern | Max Execution Time | Use Case | Chaining | Callouts | State |
|---|---|---|---|---|---|
| Future Methods | 60 seconds | Simple fire-and-forget | No | Yes (100) | No (primitives only) |
| Queueable Apex | 60 seconds | Complex async with state | Yes (no enforced depth limit in production; Dev/Trial orgs default to 5; configurable via AsyncOptions.MaximumQueueableStackDepth) | Yes (100) | Yes (serializable) |
| Batch Apex | 60 seconds per batch | Large data processing | Yes (via finish) | Yes (per execute) | Limited (Database.Stateful) |
| Schedulable Apex | N/A (calls other async) | Time-based scheduling | Via Queueable/Batch | Via called method | N/A |
When to Use Each Pattern
Batch Apex Design Considerations
| Consideration | Recommendation |
|---|---|
| Scope size | Start with 200; adjust based on processing complexity |
| Error handling | Implement Database.Stateful to track errors across batches |
| Retry logic | Build retry capability for failed batches |
| Monitoring | Use AsyncApexJob for status; consider custom monitoring object |
| Testing | Test with 200+ records; test start, execute, finish independently |
| Chaining | Chain to follow-up batch in finish method for multi-step processing |
| Governor limits | Each execute invocation gets its own governor limit context |
Queueable over Future
Queueable Apex is the modern replacement for Future methods. It supports passing complex objects (not just primitives), chaining, and monitoring through AsyncApexJob. Default to Queueable unless there is a specific reason to use Future (such as calling from a trigger where simplicity is preferred).
Platform Events and Change Data Capture
Platform Events
A pub/sub messaging system built into the Salesforce platform, based on Apache Kafka under the hood.
| Feature | Detail |
|---|---|
| Publish | Apex, Flow, API |
| Subscribe | Apex triggers, Flow, Lightning components, external systems (CometD/gRPC) |
| Delivery | At-least-once (high-volume) or at-most-once |
| Retention | 72 hours (high-volume); 24 hours (legacy standard-volume, being retired Summer ‘27). All new events are high-volume by default |
| Volume | Based on entitlement (typically 100K+/day) |
| Replay | ReplayId for event replay from a point in time |
| Transaction boundary | Published events are committed independently of the DML transaction |
Change Data Capture (CDC)
CDC publishes events when Salesforce records are created, updated, deleted, or undeleted.
| Feature | Detail |
|---|---|
| Events generated | Create, Update, Delete, Undelete |
| Configuration | Select objects to track in Setup |
| Payload | Changed fields only (delta), with header metadata |
| Subscription | Same as Platform Events (CometD, Apex triggers, gRPC) |
| Use case | Near-real-time data synchronization to external systems |
| Gap events | Published when events are missed (e.g., during maintenance) |
When to Use Platform Events vs CDC
| Scenario | Platform Events | CDC |
|---|---|---|
| Custom business events | Yes | No (CDC is record-change only) |
| Record change notifications | Can build manually | Automatic |
| Integration data sync | Manual event design | Automatic field-level changes |
| Audit trail | Custom design | Automatic change tracking |
| Custom event payloads | Full control | Salesforce-defined schema |
Big Objects
Designed for storing and accessing massive datasets (billions of records) on the Salesforce platform without consuming standard data storage.
Big Object Characteristics
| Feature | Detail |
|---|---|
| Storage | Separate from standard data storage |
| Record capacity | Billions of records |
| Query | Standard SOQL on indexed fields only; limited filtering (composite key only). Async SOQL was retired in Summer 2023 — use Batch Apex or Bulk API 2.0 for complex queries |
| DML | insertImmediate (async bulk insert) |
| Relationships | Lookup to standard/custom objects |
| Reporting | Not available in standard reports |
| Automation | Cannot trigger workflows, flows, or Apex triggers |
| Use cases | Audit logs, historical data, IoT telemetry, transactional archives |
Big Object limitations
Big Objects are not a drop-in replacement for standard objects. They cannot appear in standard reports, dashboards, list views, or most declarative tools. Queries must target the composite key, so you must know what you are looking for. Ad-hoc querying is not supported. Design the composite key carefully based on access patterns.
When Big Objects Make Sense
- Archiving historical records (old cases, audit logs, transaction history)
- Storing IoT or telemetry data that arrives at high volume
- Compliance data that must be retained for years but rarely queried
- Pre-computed analytics data for dashboards
Custom Metadata Types vs Custom Settings
Both store configuration data, but they serve different purposes and deploy differently.
| Feature | Custom Metadata Types | Custom Settings (Hierarchy) | Custom Settings (List) |
|---|---|---|---|
| Deployable | Yes (metadata API, change sets) | No (data, must be loaded per env) | No (data, must be loaded per env) |
| Packageable | Yes | No | No |
| SOQL queries | Static methods (getAll, getInstance) bypass SOQL engine entirely. SOQL queries on CMTs do not count against the 100-query limit in Apex but DO count against query rows | No (uses getInstance, no SOQL limit) | No (uses getInstance, no SOQL limit) |
| Apex test visibility | Available without SeeAllData | Requires SeeAllData or setup in test | Requires SeeAllData or setup in test |
| Per-user/profile values | No | Yes (hierarchy) | No |
| Volume | Low (configuration) | Low (configuration) | Low-Medium |
| Use case | App configuration, mapping tables, feature flags | Per-user/profile settings, feature toggles | Lookup/reference data |
Default to Custom Metadata Types
For CTA exam scenarios, default to Custom Metadata Types for configuration data. The main advantage is deployability: they move through change sets, sandboxes, and packaging like metadata, not data. Custom Settings require manual data loading in each environment, which is error-prone and breaks CI/CD.
Platform Feature Matrix
Quick reference for which platform capabilities are available across common architectural patterns.
| Capability | Declarative | Apex | API | External |
|---|---|---|---|---|
| Record CRUD | Flows | Full CRUD | REST/SOAP | Via API |
| Complex logic | Flow decisions | Full programming | N/A | Full programming |
| Scheduled execution | Scheduled Flows | Schedulable Apex | N/A | Cron jobs |
| Bulk processing | Bulk Data Load | Batch Apex | Bulk API | ETL tools |
| External callouts | Flow HTTP callout | Apex HTTP | N/A | Direct |
| Email sending | Email Alerts | Apex Messaging | API | External email service |
| File processing | Limited | ContentVersion Apex | Content API | External processing |
| PDF generation | Limited | Visualforce renderAs | N/A | External service |
| Complex calculations | Formulas (limited) | Apex Math | N/A | External compute |
| ML / AI | Einstein (managed) | Einstein API | Einstein API | Custom ML |
Related Topics
- Org Strategy: Edition-specific limits and storage
- Decision Guides: On vs off platform decision flowchart
- Trade-Offs: On-platform vs off-platform trade-off analysis
- Licensing: License types affect available governor limits
- Data Architecture: LDV strategies and Big Object usage
- Integration: API limits and integration patterns
Sources
- Salesforce Developer Docs: Execution Governors and Limits
- Salesforce Developer Docs: Platform Events
- Salesforce Developer Docs: Change Data Capture
- Salesforce Developer Docs: Big Objects
- Salesforce Developer Docs: Custom Metadata Types
- Salesforce Developer Docs: Asynchronous Apex
- Salesforce Architects: Platform Multitenant Architecture
- Salesforce Architects: Asynchronous Processing Decision Guide
- Salesforce Well-Architected: Trusted
Personal study notes for the Salesforce CTA exam. Content compiled from VJ's study notes, official Salesforce documentation, community sources, and online publicly available content, then organized and presented with AI assistance. Not affiliated with Salesforce. © 2025–2026 VJ Srivastava.