Skip to content
CipherCruCipherCru

Menu

Web Development

Web Application Integration

Two systems disagreeing about the same customer is not an integration problem. It is an ownership problem that integration made visible.

Typical duration
Two to eight months
Team shape
Two to four senior engineers
Starts with
A record ownership review
A system map showing services and the connections between them

Decide who owns the record before deciding how to move it

Almost every integration that goes wrong went wrong at the same point: two systems ended up believing they were authoritative for the same field, and the sync started resolving that disagreement by whichever wrote last.

So the first piece of work is not technical. It is agreeing, per record and sometimes per field, which system is the source of truth and which are readers — and getting the people who own each system to agree to it in writing. Once that exists, the engineering is well-understood: idempotent writes, explicit retries, a dead-letter path, and enough observability that a partner outage is visible before a customer reports it.

What usually goes wrong, and what we do instead

The pattern is consistent enough that we now start every integration the same way.

Where integrations go wrong

  • Two systems both treated as authoritative for the same field
  • A nightly job that copies data and quietly diverges between runs
  • Retries that duplicate records because the write is not idempotent
  • Failures swallowed by a job that reports success anyway
  • A partner API change discovered by a customer rather than an alert

How we build it instead

  • One owner per record, agreed in writing with the system's owner
  • Events rather than copies, so readers derive rather than duplicate
  • Idempotent writes with explicit retry and backoff semantics
  • A dead-letter path that is monitored and has an owner
  • Contract tests against each partner, run on a schedule

What we build

The parts of an integration that decide whether it wakes people up.

Record ownership design

Which system is authoritative for what, agreed in writing with the teams that own them.

API and partner integration

REST, GraphQL, SOAP and the file drops that older systems still insist on.

Event-driven sync

Changes published once and consumed by many, so readers derive their view rather than keeping a copy.

Idempotency and retries

Repeated deliveries handled as no-ops, with backoff and a dead-letter path that has an owner.

Contract testing

Tests against each partner's interface, run on a schedule, so a breaking change is caught by us.

Per-partner observability

Dashboards and alerts by integration, so an upstream outage is attributable in seconds.

How the pieces fit together

The same shape whether there are two systems or twenty: one owner per record, an integration layer that translates, and readers that derive rather than copy.

An integration layer sitting between a system of record and the applications that read from it, with a queue and a dead-letter path alongside
Stand-in artwork. The numbered legend describes the system rather than this picture.

What each part does

  1. The system of record: the one place a given record can be changed, agreed with its owner before anything is built.
  2. The integration layer: translation and validation in one place, so a partner's field names never leak into your domain.
  3. The event stream: changes published once and consumed by many, so readers derive their view rather than holding a copy.
  4. Idempotency and retry: every write carries a key, so a repeated delivery is a no-op rather than a duplicate record.
  5. The dead-letter path: what cannot be processed goes somewhere visible with an owner, rather than into a log nobody reads.
  6. Observability: per-partner dashboards and alerts, so an outage upstream is seen here before a customer reports it.

How the work runs

The same five stages as every engagement, applied to systems that have to agree.

Diagnose

What flows where today, what each system believes it owns, and where those beliefs conflict.

Decide

Record ownership, the sync mechanism and the failure semantics, written down and agreed with each system's owner.

Prove

One integration end to end in production, including its failure case, its retry and its dead-letter path.

Deliver

Integrations built one at a time, each monitored and stable before the next is scoped.

Hand over

Your team runs it with us watching, then without us.

What we build it with

Chosen for what an integration has to survive when the other side is having a bad day.

Interfaces

  • REST
  • GraphQL
  • Kafka
  • Temporal

Services

  • Node.js
  • TypeScript
  • Java
  • Spring Boot
  • Python

Data

  • PostgreSQL
  • Redis
  • MongoDB
  • Elasticsearch

Platform

  • AWS
  • Azure
  • Kubernetes
  • Datadog
  • Sentry

What you get, and when

Handed over as it is produced, not assembled at the end.

  • A map of what flows where today, measured rather than described
  • Record ownership agreed in writing, per system
  • The failure semantics for each integration, decided up front
  • Source in repositories you own
  • Contract tests per partner, running on a schedule
  • A monitored dead-letter path with a named owner
  • Per-partner dashboards and alerts
  • A runbook for each alert, including what not to retry
  • A written record of every agreed ownership decision

Questions about integration

The ones we are asked most often before a first conversation.

Should we just buy an integration platform?
Sometimes, and we will say so. Off-the-shelf platforms are good value for standard connections between well-known SaaS products, and poor value once the logic gets specific to your business, at which point you are writing code in someone else's editor with someone else's debugger. The dividing line is usually whether the transformation is business logic. If it is, it belongs in a repository you own and can test.
What if two teams both think they own the record?
That is the actual project, and it is the reason the first weeks are about agreement rather than code. We bring evidence — what each system writes today, and what downstream consumers depend on — so the conversation is about facts rather than territory. Where it cannot be resolved, we will design for a single owner with an explicit reconciliation process instead, and be clear about what that costs.
One of the systems is ancient and has no API.
That is common and workable. Database views, change-data-capture, scheduled file exchange and screen-level automation are all legitimate depending on what the system permits and what its vendor allows. We will tell you which is appropriate and what each one risks, and we would rather use a well-monitored file drop than pretend a fragile scraper is an integration.
Does this have to be real time?
Less often than people assume, and real time is significantly more expensive to operate. The useful question is how stale a reader can be before someone makes a wrong decision — for a lot of records the answer is minutes or hours, and a well-monitored periodic sync is both cheaper and easier to reason about. Where it genuinely is real time, we build for it and we say what that costs.
What happens when the other system goes down?
It is designed for rather than discovered. Writes queue with backoff, repeated deliveries are no-ops because every write carries an idempotency key, and anything that cannot be processed lands in a dead-letter path that is monitored and has an owner. The outcome you want is that a partner's outage becomes a delay and a dashboard, rather than a data-repair job the following week.
How do we find out when a partner changes their API?
From a contract test rather than from a customer. We run tests against each partner's interface on a schedule, so a changed field or a removed endpoint fails on our side before it fails in production. It does not prevent the change, but it converts an incident into a piece of planned work, which is the whole difference.

Systems that disagree with each other?

Tell us which systems and which records. We will tell you where the ownership conflict is.

Strictly necessaryEssential for the site to function: page navigation, security, session management, and remembering the cookie choices you make here.
Always on
FunctionalRemembers choices you make, such as language, region or display preferences, so the site opens the way you left it.
Performance and analyticsPerformance and analytics cookies show us how the Website is used: which pages are visited, how long is spent on them, where visitors came from, and what errors occur. They are set by Google Analytics and by HubSpot, whose cookies also link the pages you viewed to any enquiry you later send us.
Marketing and targetingTracks browsing activity to measure advertising and show relevant ads. We set none of these today, and will not without your opt-in.