Integration architecture
APIs and integrations in modern applications
Every integration is a dependency on something you do not control. Applications that stay reliable treat external systems as fallible by design: an integration layer, explicit failure handling, and a data model that remains its own source of truth.
Need help with this?
Planning an application?
Define the MVP, user accounts, integrations and operating model around the real user workflow.
Modern applications are assemblies. Payments, email, CRM, storage, accounting, scheduling and analytics all live somewhere else, and the product is the thing that makes them behave as one coherent system. That is a genuine advantage — and it means most production incidents originate on the other side of a network call.
Key takeaways
- An application should own its own data model, not borrow the shape of whichever API it happened to integrate first.
- Outbound calls need timeouts and fallbacks so a slow third party never blocks a user path.
- Inbound webhooks must be verified, deduplicated and queued — assume repeat and out-of-order delivery.
- Failures divide into transient, permanent and ambiguous, and each needs different handling. Blind retries after a write cause duplicates.
- Decide explicitly which system is the source of truth for each record before any data is synchronised.
Short answer
Keep external systems behind an integration layer, own your own data model, and design for failure explicitly: timeouts, retries with backoff, idempotency keys, verified and deduplicated webhooks, and one designated source of truth per record.
Keep the seams in one place
Scattering API calls through the codebase means every vendor change becomes a search-and-replace exercise, and every retry rule is implemented slightly differently. A single integration layer concentrates the mess where it can be seen, tested and monitored.
Application, integration layer, external services
Design for the failure, not the happy path
Every external dependency fails eventually — briefly, permanently or ambiguously. The ambiguous case is the dangerous one: the request may have succeeded even though no response arrived.
Transient, permanent and ambiguous failure
| Type | Example | Correct response |
|---|---|---|
| Transient | Timeout, rate limit, brief outage | Retry with exponential backoff and a ceiling |
| Permanent | Rejected payload, revoked credential | Stop, record with context, surface for human review |
| Ambiguous | No response after a write request | Reconcile using an idempotency key or a status query — never blind-retry |
Own your data model
It is tempting to store whatever shape a vendor returns. It is also how an application ends up unable to change providers, because its domain language is now a copy of somebody else’s schema. Map inbound payloads into your own model at the boundary and keep vendor identifiers as references.
The same question — which system holds the truth — decides whether an integrated stack becomes coherent or merely connected. That is the subject of integrating disconnected business systems.
Credentials and access
- Server-side only, scoped to the narrowest permission the integration needs.
- Rotatable without a deployment, and revocable immediately if exposed.
- Separate credentials per environment, so a test run can never touch production data.
- Logged calls without logging secrets or personal data — enough to diagnose, no more.
Know what you are taking on
Each integration carries ongoing cost: version deprecations, changing rate limits, expiring credentials and support conversations with a vendor. That is a strong argument for the discipline in what an MVP actually needs — integrate the one that the workflow genuinely depends on, and earn the rest. We work through that sequencing as part of application and PWA development.
Frequently asked questions
- What is an integration layer?
A boundary inside the application where all external communication lives: adapters, credentials, retry policy, rate limiting, payload mapping and logging. It keeps third-party quirks out of the product logic and makes replacing a vendor a contained change.
- Should an application call third-party APIs directly from the browser?
Rarely. It exposes credentials, ties the client to a vendor’s availability and makes retries impossible to control. Route calls through the server, where secrets stay secret and failure handling can be applied consistently.
- What is idempotency and why does it matter?
An idempotent operation produces the same result whether it runs once or five times. Because networks fail after a request is received but before the response arrives, retries without idempotency keys create duplicate charges, duplicate records and duplicate emails.
- How should webhooks be handled?
Verify the signature, respond quickly, queue the work, and deduplicate by event ID. Providers retry, deliver out of order and occasionally deliver twice — a handler that assumes exactly-once delivery will eventually corrupt data.
- Which system should be the source of truth?
Whichever one the business treats as authoritative for that record — and only one per record. Two-way synchronisation without a designated owner produces conflicts that are resolved by whichever write happened last, which is not a rule anyone chose.
Next step
Scoping an application build?
Define the MVP, the accounts model and the integrations before committing to a stack.
Need help with this?
Planning an application?
Define the MVP, user accounts, integrations and operating model around the real user workflow.
