Integration Best Practices
This page compiles integration best practices from official Salesforce documentation, CTA coaches, and real-world enterprise experience. Organized into four categories — design, implementation, testing, and operations — with an anti-patterns section covering what NOT to do.
Design Best Practices
1. Start with the Business Requirement, Not the Technology
Every integration decision must trace back to a business need. The CTA board will challenge you if you cannot articulate WHY a particular pattern was chosen.
| Good Reasoning | Bad Reasoning |
|---|---|
| ”Real-time sync because the call center needs current customer data during calls" | "Real-time sync because it’s more modern" |
| "Batch because the data warehouse only needs nightly refreshes" | "Batch because it’s easier" |
| "Middleware because 8 systems need shared transformations" | "Middleware because enterprise best practice” |
2. Design for Failure First
Assume every external system will go down, every network will have latency spikes, and every data payload will occasionally be malformed.
- Define error handling strategy BEFORE implementation
- Every integration touchpoint needs: retry strategy, timeout, fallback, monitoring
- Document the degraded-mode behavior: What does the user see when the integration fails?
3. Minimize Coupling
Loosely coupled integrations are more resilient and maintainable.
| Tight Coupling | Loose Coupling |
|---|---|
| Synchronous calls blocking transactions | Asynchronous event-driven |
| Direct system-to-system connections | Middleware or event bus mediating |
| Shared database access | API-based data exchange |
| Hardcoded endpoints | Named Credentials + Custom Metadata |
| Schema-aware consumers | Contract-first with versioning |
4. Choose the Right Granularity
APIs that are too fine-grained create chatty integrations. APIs that are too coarse-grained transfer unnecessary data.
The Goldilocks zone
A single API call should represent a meaningful business operation. “Create an Order with Line Items” is better than separate calls for the Order header and each Line Item (too chatty) or a single call that also creates the Account, Contact, and Payment Method (too coarse).
5. Plan for Data Volume Growth
Today’s 1,000 records per day becomes 100,000 in two years. Design integrations that can scale.
| Volume Today | Design For | Technology |
|---|---|---|
| < 1,000/day | 10,000/day | REST API (can migrate to Bulk) |
| 1,000 - 10,000/day | 100,000/day | Bulk API 2.0 from the start |
| 10,000+/day | 1,000,000/day | Bulk API 2.0 + middleware + partitioning |
6. Use Named Credentials
Named Credentials manage authentication and endpoint configuration declaratively. They eliminate hardcoded credentials, handle token refresh, and support admin-managed configuration.
- Store all external endpoints in Named Credentials
- Use Principal types: Named Principal (shared), Per User (individual context)
- External Credentials (new model) support multiple authentication protocols
- Never store credentials in Custom Settings, custom metadata, or Apex code
7. Apply the Principle of Least Privilege
Every integration should have the minimum permissions needed.
- Create dedicated integration users (not admin accounts)
- Use Permission Sets specifically for integration needs
- Scope OAuth tokens to required object/field access
- Restrict IP ranges for Connected Apps
- Enable only the APIs needed (disable SOAP if using REST only)
Implementation Best Practices
8. Use External IDs for Data Matching
External ID fields enable upsert operations and are the foundation of reliable data synchronization.
| Without External ID | With External ID |
|---|---|
| Query to find record, then decide insert vs update | Single upsert call handles both |
| Race conditions with concurrent integrations | Idempotent by design |
| Extra API calls for lookup | Fewer API calls, cleaner code |
9. Implement Idempotency Everywhere
Any operation that might be retried must produce the same result when executed multiple times.
- Use External ID + upsert for data sync
- Include idempotency keys in event payloads
- Design database operations as idempotent (upsert, not insert)
- Check for existing records before creating
10. Handle Partial Failures
Bulk operations can partially succeed. Your design must handle records that succeed alongside records that fail.
flowchart TD
A[Bulk API Job<br/>10,000 Records] --> B{Result}
B --> C[9,800 Success]
B --> D[200 Failed]
D --> E[Parse Error Details]
E --> F{Fixable?}
F -->|Yes: data quality| G[Fix Data<br/>Resubmit Failed Records]
F -->|No: systemic| H[Alert Team<br/>Manual Review]
G --> I[Retry Only<br/>Failed Records]
11. Version Your APIs
Unversioned APIs create upgrade nightmares. Always version from day one.
| Strategy | Example | Best For |
|---|---|---|
| URL versioning | /api/v2/orders | REST APIs, clear and simple |
| Header versioning | Accept: application/vnd.myapi.v2+json | When URL changes are undesirable |
| Query parameter | /api/orders?version=2 | Quick and dirty, not recommended |
12. Log Everything, but Smartly
- Log request/response pairs with correlation IDs
- Log at appropriate levels (DEBUG for success, ERROR for failures)
- Do NOT log sensitive data (passwords, tokens, PII)
- Include timestamps, source system, target system, operation type
- Use structured logging (JSON) for machine parsing
Testing Best Practices
13. Test at Every Layer
| Layer | What to Test | Tools |
|---|---|---|
| Unit | Individual callout logic, data mapping | Apex test classes, mock callouts |
| Integration | End-to-end data flow between systems | Sandbox with test environments |
| Performance | Volume, throughput, latency | Bulk load testing, JMeter |
| Failure | Error handling, retry, circuit breaker | Simulated failures, chaos testing |
| Security | Auth flows, data exposure, injection | OAuth validation, penetration testing |
14. Use Mock Callouts in Apex Tests
Apex tests cannot make real HTTP callouts. Use HttpCalloutMock and StaticResourceCalloutMock to simulate external responses.
- Test success responses, error responses, and timeouts
- Test with realistic payload sizes
- Test with malformed responses (what happens when the external system returns unexpected data?)
15. Test with Production-Like Volumes
Integrations that work with 100 records often break with 100,000. Always test with volumes that approximate production.
- Use Bulk API test jobs with realistic record counts
- Test concurrent integrations (what happens when two batch jobs run simultaneously?)
- Verify governor limits are not exceeded under load
- Test with data that triggers sharing rules, validation rules, and triggers
16. Test Failure Scenarios Explicitly
| Scenario | How to Simulate | What to Verify |
|---|---|---|
| External system down | Stop test server | Circuit breaker activates, DLQ works |
| Network timeout | Add artificial delay | Timeout handling, retry triggers |
| Rate limit (429) | Return 429 response | Backoff activates, no data loss |
| Partial bulk failure | Mix valid/invalid records | Success records commit, failures route to error handling |
| Auth token expired | Invalidate token | Token refresh, retry with new token |
| Duplicate event | Replay same event | Idempotency prevents double processing |
Operations Best Practices
17. Monitor Proactively, Not Reactively
Do not wait for users to report integration failures. Build monitoring that alerts BEFORE business impact.
- Dashboard showing integration health metrics (success rate, latency, volume)
- Alerts for: DLQ depth, failure rate spikes, API limit consumption, circuit breaker state
- Regular review cadence (weekly integration health review)
18. Document Integration Contracts
Every integration should have a documented contract that both teams agree to.
| Contract Element | Purpose |
|---|---|
| Endpoint URLs | Where to connect |
| Authentication | How to authenticate |
| Request/Response schema | Data format and validation rules |
| Rate limits | Throttling expectations |
| SLA | Uptime, response time, support hours |
| Error codes | What each error means and expected handling |
| Versioning policy | How and when versions change |
| Escalation contacts | Who to call when things break |
19. Plan for Maintenance Windows
External systems have maintenance windows. Your integrations must handle planned downtime gracefully.
- Queue messages during maintenance windows
- Automatically retry after maintenance ends
- Communicate maintenance schedules across teams
- Test integration recovery after extended downtime
20. Maintain Integration Runbooks
Every production integration should have a runbook covering:
- Normal operation description
- Common failure modes and resolutions
- How to restart/retry failed processes
- How to verify data integrity after failures
- Escalation procedures and contacts
Anti-Patterns: What NOT to Do
Design Anti-Patterns
| Anti-Pattern | Why It Fails | What to Do Instead |
|---|---|---|
| SOAP for everything | Verbose, slow, unnecessary for modern systems | Use REST as default, SOAP only for legacy requirements |
| God integration | One integration handles all data exchange | Separate integrations by business domain and timing |
| Polling every 5 seconds | Wastes API calls, false sense of real-time | Use event-driven (CDC, Platform Events, Pub/Sub) |
| Storing credentials in code | Security vulnerability, audit failure | Named Credentials, always |
| No error handling | Silent failures, data inconsistency | Retry + DLQ + monitoring + alerting |
| Ignoring API limits | Production outage when limits hit | Budget API calls, use Bulk/Composite to optimize |
Implementation Anti-Patterns
| Anti-Pattern | Why It Fails | What to Do Instead |
|---|---|---|
| Insert instead of upsert | Duplicates on retry, no idempotency | External ID + upsert |
| Synchronous for bulk | Governor limit violations, timeouts | Bulk API 2.0 for volume > 200 records |
| Hardcoded endpoints | Cannot change without deployment | Custom Metadata + Named Credentials |
| No correlation IDs | Cannot trace transactions across systems | Generate and pass correlation IDs |
| Ignoring field-level security | Integration user bypasses FLS | Respect WITH SECURITY_ENFORCED or stripInaccessible |
| Triggering recursion | Integration writes trigger flows that trigger integrations | Bypass flags, transaction control |
Operational Anti-Patterns
| Anti-Pattern | Why It Fails | What to Do Instead |
|---|---|---|
| No monitoring | Failures discovered by end users | Proactive alerting and dashboards |
| Manual retry only | Does not scale, human bottleneck | Automated retry with manual escalation for edge cases |
| No runbooks | Knowledge trapped in individuals | Documented procedures for every integration |
| Testing only in production | Risk of data corruption | Sandbox testing with production-like data |
| Shared integration user | Cannot audit or attribute actions | Separate integration users per system |
The cardinal sin
The single worst integration anti-pattern is building an integration with no error handling and no monitoring. When (not if) it fails, nobody knows until a business user reports missing data — which could be days or weeks later. By then, the data inconsistency may be unrecoverable. Always build error handling and monitoring FIRST, not as an afterthought.
Related Content
- Identity & SSO — integration security best practices depend on OAuth flows, Named Credentials, and SSO configuration
- Testing Strategy — integration testing (mocking external services, contract testing) is critical to integration quality
- Reporting & Analytics — integration monitoring and analytics provide visibility into integration health
Sources
- Salesforce Integration Patterns and Practices
- Salesforce Architect: Integration Best Practices
- Trailhead: Apex Integration Services
- MuleSoft Best Practices
- Michael Nygard, “Release It! Design and Deploy Production-Ready Software”
- Sam Newman, “Building Microservices”
- CTA coaching community anti-pattern catalogs