← All posts
COMPANY

What shipping this blog taught us

Three planes, two processes, one database — and the bug that only production could find.

Three planes had to agree before this page could exist: something to write posts, something to render them, and something to find them again. Getting each one working alone was straightforward. Getting the seams right was not.

The seam that bit hardest

The public site and the authoring API are separate processes. That is deliberate — a public, unauthenticated container should not hold the platform's LLM credentials or its session signing key. But two processes reading one database need a way to agree on when a page went stale.

The answer was a shared generation counter. The writer bumps it on every mutation; every rendered page's cache key embeds it. One write invalidates every page, and neither process has to know the other's key layout.

IN PRACTICE

The first version derived the preview-token key from the platform session key. That would have turned a compromise of a public container into session forgery. It now has its own secret, and the blog process has never seen the session key.

What the deploy actually caught

Local tests all passed. The first request to the deployed service still 500'd on search.

The cause was a stale line in a local env file pinning the vector-search project to staging. Every local run had been provisioning and querying the index in the wrong project, and agreeing with itself. Only the deployed service — which reads its configuration from the deploy, not from a developer's machine — disagreed.

A test that shares your machine's configuration is testing your machine.

What we would do differently

Provision the search collection from the deploy target rather than from a laptop. The one command that touched a real cloud resource was the one command still reading local overrides.

PR
Priya Raghavan
Co-founder of Sapient Works.

KEEP READING

ENGINEERING

Soak, then ship: our production release policy

ENGINEERING

The reviewer that never merges its own code