An integration often begins with one specific need: send orders to the ERP, synchronise customers with the CRM, or submit invoices to a provider. It works, grows, and eventually supports more processes than anyone anticipated. The problem does not appear only when volume rises. It also emerges when every change requires coordination, failures create duplicates, and replaying a message needs manual intervention.
An integration stops scaling when the effort required to change, observe, and recover it grows faster than the value it delivers. Before replacing it, identify which limit you are reaching: capacity, coupling, reliability, or operations.
Scaling is not only about moving more data
A connection can process the same number of operations and still become fragile. Every new consumer expands the impact of a contract change; every remote dependency adds latency and failure modes; every ownerless exception increases manual work.
- Capacity: the flow builds a backlog at peak time or exhausts connections, memory, or provider limits.
- Coupling: changing one field requires coordination across teams and deployments.
- Reliability: retries create duplicates, disorder, or more load while the remote system is already failing.
- Operations: nobody can trace a transaction end to end or replay it safely.
- Ownership: it is unclear who controls the contract, responds to an alert, or reconciles a record.
Six signs that the integration has reached its limit
- Retries have no clear bound. A transient fault becomes a request storm and extends recovery.
- The same operation can run twice. There is no idempotency key or deduplication rule.
- Failed messages disappear or can only be recovered by editing data directly. There is no error destination or replay procedure.
- A provider change breaks several consumers. The contract is not versioned or tested for compatibility.
- Teams compare logs manually. Correlation IDs, stage-level metrics, and alert ownership are missing.
- Releasing a change requires stopping the flow or deploying several systems together. There is no boundary that lets components evolve independently.
One signal alone does not require a complete redesign. Repeated signals show that operational cost has become part of the problem and should be measured.
Start by mapping the actual journey
Begin with one critical flow. For each step, document producer, consumer, contract, owner, normal and peak volume, acceptable latency, timeout, and what happens when it fails.
- Can the operation be repeated without producing a second effect?
- Where does a message go when it cannot be processed?
- How can a specific operation be identified and replayed?
- Which system is the source of truth for each field?
- Which change can each team release without coordinating with the others?
This map separates different symptoms. A queue can absorb peaks, but it does not fix an ambiguous contract by itself. A gateway can protect an API, but it does not prevent duplicates if the operation is not idempotent.
Choose a pattern for the failure you need to contain
If a synchronous call is still appropriate, set a timeout and bound retries. AWS recommends combining controlled retries with exponential backoff and jitter so that many clients do not retry at the same time. It also warns that retries at multiple layers can multiply load.
Source: AWS Builders' Library — Timeouts, retries and backoff with jitter
When a service remains degraded, a circuit breaker can temporarily stop new calls and provide a fallback or fail fast. Microsoft notes that the pattern should be paired with monitoring and that its thresholds depend on context; it is not a replacement for error handling.
Source: Microsoft Azure Architecture Center — Circuit Breaker
For operations with effects —creating an order, charging a payment, or issuing an invoice— an idempotency key lets the system recognise a retry and avoid repeating the action. Stripe documents this mechanism for its API; an equivalent design elsewhere must define key scope, expiry, and storage without including sensitive data.
Source: Stripe Docs — Idempotent requests
- Queue or event: decouples processing time and absorbs peaks when the consumer does not need to answer in the same call.
- Adapter: isolates frequent changes in a provider or legacy system behind a contract you control.
- Error destination and replay: retains the minimum context required to investigate and repeat an operation in a controlled way.
- Observability: propagates a correlation ID and measures latency, errors, queue depth, and message age.
Example: a synchronisation that grew without a boundary
Imagine a nightly synchronisation between an ERP and a CRM. It first copied customers in one direction. It later added contacts, opportunities, and two-way updates. When the CRM slowed down, the whole job was retried and created duplicate records. The team could only learn what happened by comparing two files.
A sensible first stage would not replace everything. It could isolate customer creation, assign an idempotency key to every operation, store failures with a correlation ID, and provide controlled replay. During coexistence, reconciliation compares source and destination. If the stage works, the same boundary can be applied to another flow; if it does not, a return path remains available.
This is a hypothetical example. Choosing between a call, queue, event, or batch depends on consistency, latency, security, cost, and the actual capabilities of the systems involved.
Checklist before redesigning
- A priority flow and its owner are identified.
- There is a baseline for volume, peaks, latency, errors, duplicates, and manual work.
- The contract and source of truth for each field are documented.
- Timeouts, retries, idempotency, and error destinations have explicit rules.
- Observability can trace one operation end to end.
- The migration includes coexistence, reconciliation, stop criteria, and recovery.
The objective is not to add more infrastructure. It is to recover a boundary that teams can understand, operate, and change. Start with the flow whose failure has the greatest impact and whose improvement can be verified without putting the entire operation at risk.
How to modernise legacy software while keeping operations running
Codiloop can help you map the integration, find its limit, and design a verifiable first stage.

