Skip to content

CONCEPT Cited by 1 source

Legacy-format emission for incremental sunset

Definition

Legacy-format emission for incremental sunset is the technique of having a new canonical service re-emit the old legacy data formats — on the original transport — alongside its new canonical format. This decouples producer decommissioning from consumer migration: legacy producing applications can be turned off immediately, because the new service is re-emitting their output format from the new canonical store; consumers migrate off the legacy format on their own schedule, within a fixed sunset window.

The name is Zalando's (PRAPI):

"Additionally, temporary components within PRAPI emitted alpha and beta formats back onto the legacy event streams. This enabled legacy applications to be decommissioned immediately, while teams gradually migrated off the legacy formats within a fixed sunset period."

(Source: sources/2025-03-06-zalando-from-event-driven-chaos-to-a-blazingly-fast-serving-api.)

Why "two-sided migration" is load-bearing

A naive cutover strategy is producer-first: turn off the old producer, everyone migrates to the new one. This fails at scale because (a) there are too many consumers, (b) you can't wait for all of them, and (c) every consumer has its own release cadence.

The inverse — consumer-first: keep producing both formats forever, let consumers migrate when they want — has the opposite problem: the legacy producer lives forever, and the team maintaining it has no off-ramp.

Legacy-format emission from the new canonical service breaks this tension:

  • The new service is the single source of both formats (it already has the canonical data; re-serialising into the legacy shape is a pure transform).
  • The old producer can be decommissioned as soon as the new service is in the critical path, because its sole remaining role (emitting the legacy format) has been taken over.
  • Consumers continue reading from the same event stream / same endpoint they always did — they don't even know the producer changed.

Requirements

  • The new service has all the data the legacy format needs. If the legacy format carries fields the canonical model dropped, those fields either must be preserved in the canonical store or re-derived deterministically.
  • The new service can emit on the old transport. Event streams must allow a new writer to take over from the old producer; HTTP endpoints must be compatible with the legacy URL/content-type shape.
  • A fixed sunset window is announced. Legacy-format emission is a temporary component, not permanent infrastructure — consumers must have a deadline.
  • Metrics on legacy-format usage — the team operating the new service needs visibility into who's still on legacy so the sunset can actually be executed.

Pairing with Accept-header negotiation

When the legacy interface was also exposed as an HTTP API (not just an event stream), the same technique maps onto Accept-header negotiation: the new service accepts the canonical type and the legacy types, returning whichever the client requests. Zalando exposes four media types on PRAPI: application/json, application/x.alpha-format+json, application/x.beta-format+json, application/x.gamma-format+json. See patterns/accept-header-format-negotiation-for-legacy-sunset.

Anti-patterns this avoids

  • Big-bang cutover — requires simultaneous readiness of all consumers; impossible at hundreds of teams.
  • Indefinite dual-writing at the producer — keeps legacy producers alive forever; team can't move on.
  • Compatibility-shim sidecar per consumer — N shims to maintain.

Seen in

  • sources/2025-03-06-zalando-from-event-driven-chaos-to-a-blazingly-fast-serving-api — Zalando PRAPI's explicit description: PRAPI emits alpha and beta formats back onto the legacy event streams, letting the old producers decommission ahead of consumer migration. The post frames this as a deliberate adoption tool to get past the "with ~350 engineering teams and thousands of deployed applications" migration coordination problem.
Last updated · 501 distilled / 1,218 read