Skip to content
heaps goodstudio
← All work
API & Backend

One typed API contract, two teams that stop breaking each other

How we make a Protobuf + buf contract the single source of truth between a Go backend and a TypeScript frontend, so API drift becomes a compile error instead of a production incident.

  • End-to-end type safety from the Go server to the browser
  • API drift caught at compile time, not in production
  • Front and back end shipping on independent cadences

A representative example: the kind of problem we solve and how we approach it, not a specific client engagement.

The problem

It is one of the most common splits in software: a Go backend and a TypeScript frontend, each holding its own private idea of what the API looks like. The real contract lives in a wiki page nobody trusts and a lot of memory nobody wrote down. So every other sprint a renamed field or a reshaped response breaks the frontend in production, and the two teams settle into a slow, defensive release train, shipping carefully so as not to startle each other.

How we approach it

We make the contract the single source of truth with Protobuf and buf, and generate both ends from it: a Connect server interface in Go and a typed Connect-ES client in TypeScript. A breaking-change check in CI turns an incompatible change from an easy mistake into one you cannot merge by accident.

Because the client is generated, a renamed field stops being a production incident a week away and becomes a compile error in the frontend, in seconds.

Why it holds up

Drift stops reaching production, because the compiler meets it first. With the contract enforced instead of merely documented, the teams can retire the release train and ship on their own cadences, each one confident the other cannot break it in the dark.

Working on something like this?