Skip to content

PATTERN Cited by 1 source

Single-source service definition

Single-source service definition defines a service's entire deploy shape — image, env vars, scaling, ingress rules, resources, health checks, IAM — in one place, and lets CI derive every downstream artifact (Kubernetes YAMLs, Ingress resources, IAM policies, deploy scripts) from that single definition. One change, one deploy step.

The failure mode it fixes

Many deploy pipelines have split a service across two or more authoring surfaces — each edited separately, each deployed separately, each with its own CI/ordering rules. The canonical trap: forgetting the order.

Figma's pre-migration shape on ECS:

  1. Author or change the service's template in Terraform (terraform apply) — this stood up an ECS task set with zero instances.
  2. Deploy the real service — this cloned the zero-instance template, substituted the image hash, and ran some instances.

Adding a single env var required (1), then (2), in that order. If you forgot the order, the env var wasn't visible to the code. Many bugs resulted.

The move

  • One authoring surface per service — Figma chose a Bazel configuration file per service.
  • CI generates all derived artifacts from that file — the Kubernetes Deployment / Service / Ingress YAMLs, the IAM policies, ConfigMaps, etc.
  • In-house deploy system applies the generated artifacts in one step.
  • No separate Terraform step to remember.

Design considerations

  • Golden path vs. escape hatches. Users shouldn't touch generated YAML directly; they should edit the single authoring file (the golden path — see patterns/golden-path-with-escapes). But occasional exotic needs require a customization surface so the golden path doesn't become a ceiling.
  • Where to put the source file. Co-located with service code (most teams) or in a central platform repo (some teams). Figma went with service-local Bazel config.
  • Generator ownership. The platform team owns the generator; a new feature (say, a new autoscaling trigger) adds a field to the authoring schema, updates the generator, and all services inherit. No service-by-service rewrite.

Why EKS made this easy

Figma specifically called this out as one of the two exceptions to their tight migration scope rule — both exceptions applied:

  • Maintaining the old Terraform-template + deploy two-step on EKS would have been "a lot of effort."
  • It's a one-way door: moving later from the two-step to the single-step is expensive because every service's definition has to be re-authored.

So the service-definition unification was shipped as part of the ECS→EKS migration, not deferred.

Seen in

  • sources/2024-08-08-figma-migrated-onto-k8s-in-less-than-12-months — Figma replaced the ECS Terraform-template + deploy two-step with a single Bazel config file that CI compiles into EKS YAMLs, applied one-step by their in-house deploy system. Explicit framing: a deploy-time dependency ordering error many developers forgot was the motivating bug class.
Last updated · 200 distilled / 1,178 read