The Polymathic Engineer

The Polymathic Engineer

The most dangerous change to a published API is a rename

Diff the spec. Fail the build.

Franco Fernando's avatar
Franco Fernando
Sep 25, 2026
∙ Paid

Hi Friends,

Welcome to the 192nd issue of the Polymathic Engineer newsletter. This week's article continues our API design series.

Last time, we focused on the core rules for creating intuitive and easy-to-evolve APIs—things like proper resource modeling, adopting standards, and reporting errors customers can build on. We wrapped up by promising to show you how to automate all of these rules: the OpenAPI Specification (OAS).

The spec describes the API's layout (e.g., endpoints, authentication, parameters, and request and response schemas) in a single machine-readable file. The tooling built around it enforces the rules. Once the layout of an API becomes a file, you can generate code from it, validate traffic against it, and, best of all, diff it in your pipeline to catch a breaking change before any consumer sees it.

The outline is as follows:

  • Why a shared spec matters

  • Generating code from the spec

  • Validating live traffic

  • Examples and mocking

  • Versioning an API

  • Catching breaking changes in your pipeline


To learn technical skills, you must work on real projects. CodeCrafters is a great platform for that. You can build your own Redis, Kafka, DNS server, SQLite, HTTP server, or Git from scratch using your chosen programming language.


Why a shared spec matters

Let’s go back to the Booking API example. When the external partner's developers start integrating your APIs, they will ask a barrage of questions: What endpoints do you have? What does the payload look like? How do we handle auth?

They can’t read your code, and relying on a handwritten wiki is a bad idea. If someone changes the API and forgets to update the wiki page, your partner risks wasting hours building against a different layout.

You need a machine-readable source of truth that tooling can actually enforce. That's where the OpenAPI Specification comes in. A spec is a plain JSON or YAML file that includes every detail a consumer needs to call your API—from paths and request payloads to auth rules and code examples.

The following snippet shows a fragment describing the booking endpoint:

paths:
  /bookings/{id}:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                required: [id, displayName, event]
                properties:
                  id:
                    type: integer
                  displayName:
                    type: string
                  event:
                    type: string

Swagger was the original reference implementation of the OpenAPI Specification, but most tooling has now converged on using OpenAPI. Today, it’s what powers those interactive dev portals and those handy "Try it out" buttons on API marketplaces.

The caveat is that a spec defines an API’s layout, not its behavior. It guarantees that GET /bookings/42 returns an object with an id and a displayName. Not what happens when someone cancels a booking that was already canceled, or if a search yields a clean 200 OK with an empty array or a hard 404. Layout and behavior are two different parts of the consumer contract.

What to write first: the spec or the code? You can hand-craft a spec and generate server boilerplate from it, or do the reverse using annotations. What matters is that the spec and the code never evolve independently: one must be generated from the other. A spec maintained by hand next to hand-written code is the one that drifts.

Generating code from the spec

The real superpower of a specification is that it lets you automatically generate client-side code to consume the API. Anyone consuming the Booking API needs the exact same boilerplate to construct HTTP requests, serialize payloads, and parse responses.

Writing all this is tedious, and integration bugs often slip in. A misspelled field name or a wrong type may not show up until the first call at runtime. Since an OAS maps out the entire server blueprint (i.e., security, paths, parameters, and schemas), a generator can produce service objects that represent and invoke the API.

The OpenAPI Generator project supports a wide range of languages and toolchains. For example, in Java you can choose between Spring and JAX-RS; in TypeScript, you can use your favorite frontend framework. Third-party developers feed the generator with your YAML file and get a complete client SDK with typed methods for every endpoint.

You can also generate server implementation stubs, such as skeleton controllers with routes and parameter types, plus empty method bodies to fill in with logic. This is what makes the spec-first workflow from the previous section practical — the producer and the consumer agree on the layout, and generate their scaffolding from it.

The generated code acts as an automated sanity check for the integration over time. When the spec changes, regenerating the client turns structural mismatches into immediate compilation errors instead of runtime surprises. A renamed field stops the build immediately. It is annoying in the moment, but better than a parser silently returning null values in production.

Validating live traffic

You could think that if producer and consumer generate their code from the same spec, nothing can go wrong. But generation happens at build time, and the network is full of clients you don’t control. Some consumers hand-write their integration, some run an SDK generated from an outdated spec, and some traffic isn’t a well-meaning consumer at all.

This post is for paid subscribers

Already a paid subscriber? Sign in
© 2026 Franco Fernando · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture