How to integrate
You spent the implementing phase making one part correct on its own, and you could, because a part is small enough to hold in one head. Integration is where that part joins a whole, and a whole is not simply more parts. It has properties of its own, shared fate, feedback, rules that span everything, a health unlike that of any piece, and none of them lives inside the thing you built. Here MANIFESTO.md meets its companion THE-SHAPE-OF-THE-WHOLE.md: the manifesto is the book of the part, build each piece so a tired person can reason about it alone; the companion is the book of the whole, the failures that belong to the composition and to no component. Integration is the hinge between them, the phase where local correctness stops being enough and you must fit your part to a whole whose rules it cannot see from inside. The objective is the parent's, in the join's clothes: minimise what a tired engineer must hold in their head to fit this part into the whole, subject to a bounded blast radius for the shared parts and for anything an attacker or an unlucky caller controls. Every move below takes a lever the manifesto gave you inside your part and points it at a property the companion says the whole owns and no part does. It runs both ways: the whole can break your part, and the instant you connect it, your part can break the whole. None of it is free.
Learn the whole before you wire into it
A part cannot see the system it is joining, so before you add your edge, go and learn what the whole already shares, depends on, and fails together through.
The first move is to study the whole you are about to become part of, before you write a line that touches it. Your part will sit on a foundation it did not choose: the same name resolver, the same config store, the same identity provider, the same region, the same handful of services that everything quietly leans on. Anything sitting under both your part and the rest is a single thing whose bad day is now everyone's bad day at once, and it is the dependency no diagram shows, because nobody added it on purpose. (This is the companion's first law: that two things are independent is a claim about the whole you have to check, never a property you get for free.) A new dependency can resolve through the same DNS another service already leans on, or hide a boot cycle three deep, one service waiting on config waiting on the registry waiting back on the first, that deadlocks the whole system from a cold start and never shows in daylight, because the cache is never empty. An hour with the traces and the infrastructure code draws the real graph you are joining.
- A cold start: read a cold-boot trace for the cycle that only deadlocks the system with an empty cache, rather than trusting a start-up order that has merely happened to hold so far.
- A common dependency: list what your part and the rest genuinely share, pools, zones, secrets, control planes, before you trust that a box drawn on its own actually stands on its own.
- An upstream table: find out whether the table you are about to read already feeds half the platform, so you learn its blast radius before you add yourself to the list of things that fall when it changes.
Tension: A map of the whole is itself a thing that rots, and a year-old diagram is worse than none, because it is the one you reach for in the incident it no longer fits (tenets XIV, XX). So derive the picture from traces and the infrastructure code instead of drawing it by hand, learn only the shared pieces whose joint loss would genuinely hurt, and write down which corners of the whole you left dark.
Ask yourself: What does the system I am joining already share underneath, and have I actually looked, or am I assuming my part lands somewhere clean?
Pin your part's one boundary onto the whole
The contract at your edge is the one piece of the whole your part actually controls, so write it down and parse what crosses it into a checked value, and an ambiguity at this seam cannot slip inward to surface as someone else's corruption deep in the whole.
Most of the whole is out of your hands; the boundary where your part meets it is not. That seam is the one thing you own outright, so make it exact. State the contract somewhere both teams can read and a test can enforce, and parse what comes across into a typed, checked value at the first line on your side (tenets XV, III). A boundary running on "we both roughly know the shape" drifts the day either side renames a field, and the drift does not surface at the seam; it surfaces as a corrupt row three services deep into the whole, far from the change that caused it. If one side reads an amount as minor units while the other, for one currency, sends major units, and nothing written down says which, a hundredfold error crosses the seam and then spreads wherever that figure travels. Be generous about the shapes you accept inside the contract and exact about the ones you emit, so your part is never the source of an ambiguity the rest of the whole inherits.
- A breaking change: a consumer-driven contract test that breaks your build the moment you change something a caller relies on, rather than a schema doc that quietly drifts from the wire and is right about nothing.
- A client response: parse the response into a typed model at the boundary and render an explicit error on the shape you did not expect, instead of threading a raw object inward to crash six components deep.
- A column contract: pin the column types and units in a schema the producer and consumer both build against, rather than two jobs agreeing by habit until one of them changes and the skew rides downstream into every table built on it.
Tension: Generosity and exactness pull against each other, and a parser that swallows anything becomes the ambiguity it was meant to remove. Accept the variations the contract genuinely allows and reject the rest loudly at the door, because a reader that silently coerces a bad value into a plausible one is just a swallowed error (tenet XIII) with good manners.
Ask yourself: If the far side sends a shape I did not plan for, does my part reject it at the boundary with a clear message, or pass it inward to fail somewhere a reader can't trace back to here?
Bound what the whole can do to your part
The whole will have a bad day on a schedule you do not control, so put a deadline on every wait, cap and scatter your retries, break the circuit, and keep a way to run without the piece that failed.
Now defend your part against the whole, because the whole is large and something in it is always failing. Every call you add hands a thread of your part's fate to a piece you do not run, so wire it so that piece's bad day stays its own: a deadline on the wait, retries that are capped and jittered rather than tight, a breaker that trips when the far piece is plainly down, and a decided fallback so your part degrades instead of dying when something it leans on goes away (tenets VI, VII, XIX). Skip it and a slowdown in one corner of the whole becomes an outage in your part: it waits without limit, retries hard, and a part that was perfectly fine goes down with the piece it was calling.
- A blocking call: a deadline that frees the thread the instant the budget is spent, not an open wait that lets one slow corner of the system pin your whole pool.
- An absent service: render without the piece that is missing, a degraded view chosen in advance, rather than a blank screen because one call into the whole came back empty.
- A dependency outage: a breaker and a fallback for the dependency that is down, so your part keeps serving what it still can instead of failing whole alongside it.
Tension: A part that flinches at the whole's every hiccup never does its job, and a deadline too tight or a breaker too twitchy throws away work that would have completed. Set the bounds off the latency you actually observe across that edge, not off nerves, and make every fallback announce that it fired (tenet XVIII), because a degraded path nobody can see is only a quieter way to fail.
Ask yourself: When a piece my part leans on gets slow or vanishes, does my part shrink to what it can still do, or does it fall over and drag its own callers down with it?
Bound what your part can do to the whole
The moment you connect it, your part is a force on the whole, so bound what it emits and consumes, and make sure its worst behaviour can only take down your part, never the system.
Defence is half of it, and the half people forget. Your part is not only exposed to the whole; it now acts on the whole, and a new part is precisely how a stable system gets tipped over. Retry hard into a struggling dependency and your part is the retry storm that holds it down (the companion's second law, the loop that keeps itself going on the load it makes, only now you are the one who started it). Become the thing everyone finds it handy to call and you are the new shared foundation whose outage takes the lot (the first law, pointed outward this time). Take an unbounded share of a shared pool, a connection limit, a rate budget, and your part quietly starves features that have nothing to do with it. So bound your part's footprint on the whole: cap what you emit, back off the moment you are asked to, hold to your share of shared resources, and shed your own excess at your own door (tenets VII, V, XIX), so that when your part misbehaves the damage stops at your part and does not spread into the system. Unbounded retries do both jobs at once: they hammer a recovering dependency back into the ground and drain the shared pool until unrelated features go dark, none of which had anything to do with your part.
- A retry policy: capped, jittered retries behind a breaker, so a wobble on the far side cannot become a stampede that your part drives into it.
- A resource budget: a quota on the shared pool your part draws from, so your part's busy hour cannot starve every other tenant of the same resource.
- A popular endpoint: if everyone now calls your part, cap its fan-in and keep its absence survivable for callers, so the endpoint everyone finds handy cannot harden into the shared foundation whose outage takes them all down.
Tension: Bounding your own footprint costs you throughput and feels like tying your own hands, and a part too timid about its effect underdelivers on a calm day. But the asymmetry is the whole point: a part that underperforms is a nuisance, while a part that can take down the system is a hazard (the parent's tie-break, who controls the input and how far the damage spreads). Spend the restraint where your part could plausibly be the trigger or the shared load, and nowhere it could not.
Ask yourself: On its worst day, can my part only fail itself, or can it reach out and bring down the whole, by hammering, by hoarding, or by being the thing everyone now depends on?
Give the rule the whole needs, and no part owns, a home
Some rule has to hold across three or more parts of the whole and no single part can see far enough to keep it, so decide out loud where it lives, and pay for coordination only where breaking it costs more than the coupling does.
With your part wired in, a rule now spans it and others that none of them, alone, can keep: a payment captured at most once across your service, the provider, and the webhook that confirms it; an order that is never both shipped and refunded across the three workflows that touch it. This is the rule the whole depends on and no part owns, and left unsaid it holds only as long as every part happens to behave, which is the swallowed error written at the size of the system. (The companion's third law is the long account of why this is the hardest class of bug there is: a rule over three or more parties, invisible from inside any single one.) So make it a decision you write down: pick the rule's home and put a name on it. A coordinator that makes the call in one place, a single owner of the fact, a saga that runs the steps in order and carries an undo for each, a quorum, or an honest sweep that runs afterwards, finds the drift across the parts, and repairs it. A rule like "capture at most once" that lives nowhere in particular holds right up to the morning a retry crosses a redelivered message and a customer is charged twice.
- A one-time action: "captured at most once" wants one owner, a fenced lease, or an idempotency key every party honours, never each node trusting its own local view.
- A multi-service workflow: "create the order, charge the card, reserve the stock" is one rule wearing three services, so run it as a saga with a compensating refund and release, not a distributed transaction strung across all three.
- A replicated fact: "these stores all agree" wants one writer and a reconciliation job that names the drift out loud, rather than several writers and a hope.
Tension: Coordination is the most expensive thing you can add here and the easiest to over-buy. A coordinator is a fresh single point of failure and a new shared dependency, straight back to move I; a consensus group gives up availability the instant the network splits. So spend the heavy machinery only on money, on safety, and on the steps you genuinely cannot repeat (tenets XIV, X), and let the rest run eventually consistent with a sweep behind it.
Ask yourself: Which rule does the whole rely on that no single part can see, where does it live today, in a home or in a hope, and what does keeping it cost set against what breaking it costs?
Compose your control loops with the ones the whole already runs
Your part brings feedback loops to a whole that already has its own, and loops each stable alone can drive the whole into oscillation together, so know what each reads and writes, keep them off the same timescale, and give one authority over any lever they share.
Your part has control loops, a retry policy, a cache that fills and drains, perhaps an autoscaler, and the whole you are joining is already full of them, rate limiters, shedders, scalers, breakers, every one tuned and proven on its own. Connect yours to theirs and the behaviour that emerges belongs to the whole and to no controller in it: each reacts correctly to a signal another is busy moving, and the system hunts instead of settling. (The companion's fourth law is the control-theory account of why stable-alone tells you almost nothing about stable-together.) A new retry loop meeting an edge whose far side already enforces a rate limit can slide in and out of phase with it, so the join flaps while each side, measured alone, looks perfectly steady. So before you turn it on, name the loops your part adds and the ones already running, write down which signal each reads and which it moves, keep two that pull the same lever on different timescales so the fast one settles before the slow one stirs, and where they must share a lever, give one the final say and make the other defer.
- A scaling loop: an autoscaler and a load shedder reading the same latency, one adding capacity while the other rejects traffic, each undoing the other's correction unless one is told to wait.
- A breaker loop: a retry policy and a circuit breaker tuned in separate rooms, so the breaker ends up opening and closing in a rhythm the retries themselves are driving.
- A client loop: a client backoff and a server rate limit whose windows fall into step, so the join swings back and forth while both sides insist they are behaving.
Tension: Damping a loop costs you speed, and a loop slow enough that it can never oscillate is also too slow to catch a real fault. Worse, designing the loops together pulls against the independent deployment that made them separate controllers in the first place. There is no free version: model the coupled pair where the loops demonstrably touch, and leave the rest alone, because most of them never meet.
Ask yourself: When my new loop and the ones already in the whole all react to the same signal at once, does the system settle, or have I only checked that each loop behaves on its own?
Join in the dark, then ramp into the whole
Your part will be wrong about something on first contact with the whole, so connect it switched off, with a fallback for its absence, and ramp the traffic across; every edge you add is a promise you have to keep at the whole's worst moment.
Everything so far was design. This is how you let the design meet the real whole without betting the whole on it. Land it dark: ship the new dependency disabled behind a flag, make your part fall back cleanly when the far side is absent, and walk the traffic from a trickle to all of it, with the path back in place before the first real request crosses (tenets XX, XIX, and the flag and canary of the operating guide). Cut it in for everyone at once and the first bad assumption meets full production traffic with no toggle to reach for, only a hotfix to survive while it burns across the whole. Wiring it in dark would have caught the same fault at one per cent of traffic, an incident instead of a system-wide outage. An edge with no fallback is a vow to be perfect at the exact moment the other side is at its worst, and that is the one moment nothing is.
- A risky cutover: the new dependency behind a flag, defaulting to the old path while it is off or unhealthy and ramped one per cent to a hundred, rather than a hard cut you can only undo by shipping again.
- A new client call: render the page without the new service when it is missing, a degraded view you decided on in advance, not a blank screen because one new call came back empty.
- A new pipeline: run the new pipeline alongside the old and compare the outputs before you switch reads over, instead of trusting the join on its first contact with real data.
Tension: Every flag and every fallback path is clutter the day the ramp is done (tenet XXI), so add the seam only when the edge is genuinely risky or wide, and give it a date to die the day you add it. A flag on a trivial, reversible change is ceremony, not safety, and a fallback you never exercise is just a second bug lying in wait for the worst moment (tenet XXIV).
Ask yourself: If this edge is wrong at full traffic, is the fix a toggle I flip in seconds, and when the far side is down, does my part degrade or simply stop?
Prove the whole still works, not just your part
A green check on every part is not a working whole, so before you call it integrated, send a real request, and a real fault, the entire way along the path that now runs through your part.
Your part passing its own tests proves the part. It says nothing about the whole, because the failures you are now exposed to live between the parts, in the route, not the nodes. So exercise the whole path the way a user does, end to end, against a deadline rather than a heartbeat. Per-part health will not stand in for it: every box can read green, up, answering, calm on its own dashboard, while the request that has to cross all of them quietly times out in the middle. (The companion calls this gray failure: bad enough to break the journey, too mild to trip any single check along it.) You cannot add green parts up into a working whole: each service can add a sliver of tail latency that is harmless alone and fatal once it stacks across the route your new hop has lengthened, every check still green. The demo had worked; the integration had not, because nobody had sent a request the whole way. So trace the path edge to edge against a budget, and provoke the join on purpose with a fault you inject in daylight, rather than meeting the same fault at three in the morning.
- A request path: an end-to-end trace against a deadline that shows the latency adding up across the new hop, rather than a row of green checks each calling its own node fine.
- A health probe: a synthetic request that walks the full route and catches the node passing its liveness probe while it drops one packet in twenty, which no dashboard of healthy instances will show you.
- A pipeline result: an end-to-end check that the joined output is actually right, because what was correct was the stages agreeing, and no single stage was watching the agreement.
Tension: Whole-path probes and fault injection are themselves load, and themselves risk (tenets XVIII, VII). A game day is a controlled outage and synthetic traffic is real traffic the system has to carry. So run the drills you will actually act on, on the routes whose failure would genuinely hurt, and bound the probe budget like anything else a caller can grow without limit.
Ask yourself: Does every part report green while the route across them is red, and have I actually pushed a request, and a fault, the whole way through the system my part now sits in?
Own the new whole you have made
The adapter that quietly became load-bearing, and the dependency nobody owns, are the 3am problem, because adding a part changes the whole, and someone has to own the whole you changed; so give every edge a name and a sunset the day you add it.
You did not just connect a part; you changed the whole, and the new whole has a shape someone now has to answer for. Process is the structure you fall back on once code structure runs out (tenet XXV), so as you hand it over, give the edge one owner of record and a date to be reviewed or removed (tenet XX). An edge with no owner is the one where "whose is this?" is the first frantic question of the incident, and a contract test with no owner goes flaky, gets skipped in CI, and ends up guarding nothing. A throwaway shim, written to bridge a migration, ends up still load-bearing in the whole eighteen months on, its contract test long since muted because it flaked and the name attached to it had left. So make the test that guards the boundary part of what the owner keeps green, so the seam your part opened into the whole never decays back into folklore.
- A temporary shim: an adapter that ships with a named owner and a removal date, not a "temporary" shim that hardens into permanent infrastructure no one will touch.
- A dependency edge: a dependency edge recorded with its owner and the reason it exists, rather than a call added in a hurry that nobody can later explain or safely cut.
- A contract test: a contract test kept green and owned, instead of one skipped after it flaked, leaving the agreement across the stores enforced by nothing at all.
Tension: This is accountability, not paperwork. An expiry on an edge that genuinely has to stay is a false alarm you learn to ignore, and that trains you to ignore the real ones. So set sunsets that mean something, and for the edge that really is permanent, make "owned by X, reviewed each quarter" the decision you wrote down rather than the silence you defaulted into.
Ask yourself: For every edge this change adds to the whole, can I name its owner, its expiry, and the test that still guards its contract, or is it a shim that has quietly gone load-bearing?
The through-line
Every move here is the manifesto's one move raised to the level of the whole: you take the levers it gave you inside your part, the contract, the bound, the owner, the loop, the flag, the probe, and aim each at a property the companion says no part owns, shared fate, a rule across many parts, the stability of coupled loops, the health of the route. You push those properties out of memory and out of nobody's component and into the structure of the composition, so they hold whether or not anyone remembers them, and you do it both ways at once, guarding your part from the whole and the whole from your part.
Write for the engineer who reaches this seam at 2am with the pager going off, knowing their own part but not the whole it joins. Make the shape of the whole something they can read rather than reconstruct, and never make them hold the entire system in their head to make one safe change, because the failures of a composition belong to no one until the night they belong to everyone.