Skip to main content

Strangler Fig — Incremental Legacy Replacement

Incrementally replace a legacy system by routing new traffic to a new implementation while the old one still runs.

When to use

  • Migrating a monolith to services
  • Replacing a legacy API too risky to rewrite in one shot
  • Need to ship continuously during migration

Tradeoffs

  • Two systems in production simultaneously (data sync complexity)
  • The facade routing layer becomes critical path during migration
func router(legacyHandler, newHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if isNewFeature(r) {
newHandler.ServeHTTP(w, r)
return
}
legacyHandler.ServeHTTP(w, r)
})
}

func isNewFeature(r *http.Request) bool {
return strings.HasPrefix(r.URL.Path, "/v2/")
}

Gotcha: The facade IS the product during migration. Don't treat it as a throwaway — test it like production.