Nonprofit & PaymentsField engagement

Improving the giving experience on a site the organisation will not let anyone rebuild, which makes the migration itself the architecture.

Architecture and hardening lead.
The approach, in four words
replace path by pathshared gift core beneathevery step reversiblethe seam is designed
Is this request on the donor path?NOYESthe existing sitethe rebuilt journeyReaches the site unchanged,which is most of it, so thesurface area of the change isexactly the path beingRouted to the new path overthe shared gift core, cut overon its own and routed backjust as easily.
A rebuild was rejected, correctly, for a live organisation taking gifts. Replacement happens path by path behind the existing site, and every step is individually reversible.
What was at stake

The donor journey needed to get noticeably better on a website that was not going to be replaced. A full rebuild had already been proposed and turned down. For a live organisation taking real gifts, that refusal was not timidity. A rebuild puts all of the organisation's giving on one cutover, and if the cutover goes wrong the cost is not a delayed project. It is a donate page that fails in the middle of an appeal, and gifts that simply never happen.

How this works

A strangler migration grows the new system around the old one until the old one has nothing left to do.

The name comes from the strangler fig, a plant that grows around an existing tree and gradually takes over its place until the tree inside is no longer needed. In software it describes replacing a system piece by piece while it keeps running. Something sits in front of the old system and sees every request. For most requests it does nothing and passes them through. For requests that belong to a piece that has been rebuilt, it sends them to the new code. Over time more requests go to the new code, and eventually the old system receives none.

The routing layer is what makes this safe. Moving a path from old to new is a change to a routing rule, not the launch of a whole new site. Moving it back is the same change in reverse. So each step can be small, can be tried with real traffic, and can be undone in the time it takes to change a rule. A full rebuild works the other way round. The new site goes live all at once on a cutover date, and the only way back from a serious problem is to switch the whole site back and lose everything that went live with it.

The price is a period in which two systems run at once. A donor might begin on an old page and finish on a new one. Whatever they carry across that boundary, the session they are in, the campaign that brought them, the amount they picked, has to survive the crossing. Reporting has to understand both sides. A change to something shared, such as the site header or a policy link, has to be made in two places. None of this is hard, but all of it has to be planned, because the seam is where incremental migrations go wrong.

A donation journey adds one more rule. The new paths must not bring their own payment handling. They sit on the same gift core as the old ones, so whether a gift came through an old page or a new one, it is confirmed, deduplicated and reconciled in exactly the same way. The migration changes what the donor sees. It leaves the guarantees about the money alone.

The gate
Is this request on a donor path that has moved?
Rebuilt donor journey
new experience, same shared gift core
Existing site, unchanged
served exactly as it was before
Rollback is the same rule with one path taken off the list.
FigureThe single decision at the heart of a strangler migration. Every request passes through it. Moving a path to the new journey, or back again, changes which paths answer yes, and nothing else on the site moves.
The constraint

So the journey is replaced incrementally, behind the existing site, one path at a time, with the reliable gift core underneath every new path. The limit on the work was never technical skill. It was blast radius. At no point could the organisation be more than one path away from its last working state, and that rules out any approach whose value only arrives at the end.

Where it usually breaks

Incremental migrations fail at the seam, or by never finishing.

The common failure is the boundary between old and new. A donor starts on an old page, follows a link to a new one, and arrives without the campaign they came from, or the amount they picked, or with a session the new code does not recognise. Each side works on its own and the crossing loses something. Tests usually exercise one side at a time, so the crossing is the least tested part of the system and one of the most travelled.

The other failure is a migration that stalls. The easy paths move early, the awkward ones are left, and the organisation ends up running two systems indefinitely, with the routing layer as permanent infrastructure nobody planned to own. A strangler migration needs a plain record of which paths have moved and which remain, or the halfway point quietly becomes the end state.

01

Context lost at the crossing

A donor moves from an old page to a new one and the campaign tag, chosen amount or session does not come with them. The gift still happens, credited to nothing.

02

Two payment paths

The rebuilt journey brings its own payment handling. Gifts are now confirmed in two different ways depending on the page, and the two will drift apart.

03

A cutover with no way back

A path is moved by deploying over the old version. When something goes wrong there is no rule to flip, only a redeploy under pressure.

04

The permanent halfway house

The difficult paths never move. The organisation runs two systems and a router for good, without ever having decided to.

05

Shared changes made on one side

A site-wide change is made on the old site and forgotten on the new paths, or the reverse, and donors see two versions of the same organisation.

Old campaign page
knows where the donor came from
Link into the rebuilt journey
carries the donor but not their context
Rebuilt donate path
works correctly with what it received
Gift core and records
faithfully record an unattributed gift
The failure point
Context lost crossing the seam
a gift recorded with no campaign
Each side passes its own tests.
Nobody tests the crossing unless someone designed it.
The seam is a feature of the system for as long as the migration runs. Treat it as one.
FigureThe typical failure in an incremental migration, shown on a donor journey. Both sides behave correctly. What gets lost is whatever the donor was carrying when they crossed from old to new, and only a designed boundary prevents it.
The fork

The reflex, and the fix.

Road not taken

Propose a full rebuild

Pull

It is the clean answer, and the existing site genuinely limits what the donor journey can become.

Why not

It was turned down, correctly, as too risky for a live organisation taking gifts. An approach that only pays off at cutover is also an approach that cannot be stopped halfway, and if it is stopped it leaves nothing of value behind.

Road taken

Intercept and rebuild path by path

Accepted

Two code paths living side by side during the migration, and a routing seam between them to design and look after.

Bought

A better donor journey arriving in pieces, the rest of the site untouched, and every piece individually reversible.

Decision

The organisation has to keep taking gifts on every day of the migration. A rebuild cannot promise that and path-by-path replacement can, so the journey was replaced one path at a time.

How it was built
01Existing site
›
02Route check
›
03Rebuilt journey
›
04Gift core
›
05Records
01

Interception at the level of a path

Requests for a donor path being replaced are routed to the rebuilt journey. Everything else reaches the existing site exactly as before, so the surface area of each change is the one path being replaced and nothing more.

02

The reliable gift core underneath

The rebuilt journey sits on the same webhook-confirmed, idempotent, reconciled gift core as everything else. Payment handling is not written a second time for the new path.

03

One path at a time, each reversible

Each path is cut over on its own and can be routed back. The organisation is never more than one step from a state it knows works.

04

A seam that is designed

Two code paths coexist while the migration runs. That is stated openly, and what happens at the boundary between them is designed in advance so that it is never discovered by a donor.

Inside the key decisions

What each choice cost, and what it bought.

ARouting at the level of a path

The rebuilt journey is reached by intercepting specific donor paths in front of the existing site. That put a routing layer into every request, which is one more component to run and understand. It bought changes that are exactly one path wide, and a way back that is a rule change. Replacing pages in place on the existing site would have avoided the router, and it would have turned every rollback into an emergency redeploy.

BNo new payment handling on the new paths

The rebuilt journey sits on the existing gift core and does not touch payments itself. That meant the new journey had to live within the core's contract, and payments could not be redesigned in the middle of the migration. It also meant gift reliability was identical on both sides of the seam for the whole migration. Giving the new paths their own payment handling would have looked cleaner and created two definitions of a confirmed gift, one per side.

CReversibility as the unit of progress

A path only moved once it could be moved back. Each step therefore needed a working route back, and the old version of the path had to stay alive and correct until the new one had proven itself. That is slower than moving several paths at once. It is also the property that kept the organisation within one step of a known-good state throughout, which was the whole reason the rebuild had been refused.

DNaming the seam as a cost

The coexistence of two code paths was stated plainly from the start, and the behaviour at the boundary was designed and checked. That meant admitting the approach has a price, and spending effort on a boundary that will eventually disappear. The alternative, presenting incremental replacement as free, ends with donors discovering the seam one lost campaign tag at a time.

  1. Choose one donor path
    nothing else on the site is in scope
  2. Rebuild it on the core
    no new payment handling
  3. Route the path across
    a rule change, not a redeploy
  4. Check the boundary behaviour
    what crosses from old to new survives
  5. Route back if anything fails
    the old path is still standing
At every point in this sequence the organisation is one rule away from where it started.
FigureThe life of one path in the migration. Every path goes through the same short sequence, and the old version stays in place throughout. Progress is counted in paths that have moved and could still move back.
How it was measured

A single headline number hides where a system fails. This work was scored on the dimensions that actually decide whether it holds in production, measured on real, held-out cases rather than the demo path.

Blast radius of each cutoverReversibility of an individual pathBehaviour at the boundary between old and newGift reliability across both paths
Full rebuild
Value arrives at cutover
nothing usable before the switch
Every path switches together
the whole site is in the blast radius
Rollback means everything
and gifts are at stake while it happens
Path by path
Value arrives per path
each improvement is live once it moves
One path switches at once
the blast radius is that path
Rollback is one rule
the old path is still there
Same destination, different exposure
Gift reliability is held constant on both sides because both sides share one core.
FigureHow this work is judged, since no figures are published for it: by the shape of the risk at each step. A rebuild concentrates all of it on one date. Path-by-path replacement breaks it into small pieces, each of which can be undone on its own.
figures

No measured figures are published for this engagement. Outcomes are described qualitatively.

What it produces
Without this discipline

A rebuild proposal that is turned down, after which nothing changes at all. Or a rebuild that is accepted, and puts a live organisation's giving on a single cutover date.

This system

A donor journey replaced path by path behind the existing site, each step reversible, all of it on one shared reliable gift core, with the migration seam designed and acknowledged.

replace path by pathshared gift core beneathevery step reversiblethe seam is designed
The operating envelope

What it owns, and what it hands to a person.

Handled with confidence
Donor paths cut over individually
The existing site left otherwise unchanged
Rollback of an individual path
Flagged for review
Behaviour at the boundary between old and new paths
Out of scope by design
Replacing the existing site
Changes outside the donor journey
The honest limit

Incremental replacement limits the risk, and it means two code paths coexist for as long as the migration lasts. That seam has to be managed openly for its whole life. It is a genuine cost of not doing the rebuild, and it is presented here as one.

What it generalizes to

To improve a live system you are not allowed to replace, put a routing layer in front of it, rebuild one path at a time over a shared reliable core, and keep every step individually reversible. The old system stays standing as the fallback until the last path has moved.

What to take from this

If a live system cannot be replaced, it can usually be surrounded. Put a routing layer in front of it and move one path at a time.

Make each step of a migration reversible by a configuration change and not a redeploy. The ability to go back is what makes it safe to go forward.

The seam between old and new is where incremental migrations break. Decide in advance what a user carries across it, and test the crossing on purpose.

Do not let new paths reimplement something critical that the old ones share. Put them on the same core, so the migration changes the experience and leaves the guarantees alone.

Keep a written list of what has moved and what remains. Without one, the halfway point quietly becomes the permanent architecture.

How we engage

You have a system like this one.
Tell us where it stands.

Whether it is failing, not yet built, or about to meet a scale it has never seen, we can tell you what we see.

Start a conversation
mostafa@opulion.dev · Response within 24 hours · By inquiry