gofri Why two g's? When I was a kid my grandma called me Gofri, and the family picked it up. She said the G hard, almost twice, so I write it twice.
production

Strangler migration

for
Ticmas
when
2024
Problem
A backend that had to move without stopping.
My contribution
Selected the migration strategy and implemented the facade while the team migrated endpoints.
Result
More than 80% of the backend migrated by Nov 2024, including all important endpoints.
Status
production · 2024

>80%of the backend migrated before I left, all important endpoints

  • GET /classes
  • GET /projects
  • POST /assignments
  • GET /reports
One facade, endpoints moving to the new backend one at a timereconstruction, illustrative

try it

One endpoint, earning its traffic

One endpoint, from shadow to promoted

reconstruction, illustrative

stateShadow

matches
0 of 10
differences
0 of 10
failures in a row
0 of 5

the client getsthe old response

The new code runs only on dry-run requests, and its answer is compared with the old one.

states

Four states, one endpoint at a time

  1. 1ShadowA new endpoint reports ready and becomes a candidate. The old code still answers; the facade tracks each endpoint's state in Redis.
  2. 2PromotedEnough matches: the facade serves the endpoint from the new code.
  3. 3ReviewDifferences came first, so a person looks at them before promotion.
  4. 4FailingRepeated failures: traffic goes back to the old code until a manual reset.

rules

What moves an endpoint between them

  • whena new endpoint reports ready (readyz)thenit becomes a shadow candidate; clients still get the old response
  • whena request carries the dry-run headerthenit also hits the new code, and the two responses are compared asynchronously
  • when10 matchesthenthe endpoint is promoted to the new code
  • when10 differences before 10 matchesthenit goes to review
  • when5 failures in a rowthenit switches to failing and routes back to the old code until a manual reset
  • whena difference is intendedthena manual success override lets it through

order

Critical endpoints went first

  1. Feature work pauseduntil the stress tests passed; easy and important endpoints, then hard and important ones
  2. About five critical endpointsmigrated within one month
  3. Winter-camp loadmonitored for two weeks without observed interruptions

ownership

Who did what, and when

  1. strangler strategyfacade in front of the old backend
  2. stress testsfeature work paused until they passed
  3. critical endpointsabout five, within one month
  4. winter campmonitored for two weeks, no observed interruptions
  5. most of the backendover 80% migrated before I left
  • MeChose the strangler strategy, wrote the facade and set the order of endpoints
  • A platform engineerProposed the hexagonal architecture I accepted
  • Other engineersMigrated the endpoints
  • A reliability guaranteeNot claimed: the camp result is monitoring, not uptime

What shipped

More than 80% of the backend migrated, including all important endpoints.

before I left; the team migrated the endpoints, I wrote the facade
  • More than 80% of the backend was migrated before I left, including all important endpoints.
  • Approximately five critical endpoints migrated within one month; I monitored the winter-camp operation for two weeks without observed interruptions.
  • Approximately 80% fewer PBL tickets blocked by another team, comparing a full quarter before and after.
Method and caveats

The camp result is monitoring-based observation, not an uptime guarantee. The blocked-ticket figure has no total-ticket denominator and is not a blocked duration or a normalized rate; it is separate from the migration percentage.

  • More than 80% migrated before I left, including all important endpoints: my account of the migration
  • About five critical endpoints in one month, then two weeks of monitoring without observed interruptions: monitoring-based, not an uptime guarantee
  • Approximately 80% fewer PBL tickets blocked by another team across a full quarter: no total-ticket denominator, and not a blocked duration or a normalized rate
  • Counts in the simulator (10, 10, 5) are the facade's defaults as I recall them; the simulator itself is illustrative