Spanner Architecture Notes
Design notes for Meridian's recipe Spanner layer. Spanner provides globally consistent transactions across multi-region recipe data, with TrueTime-backed external consistency. These notes cover schema interleaving, secondary indexes, and read patterns we rely on in production routing decisions.
1. Schema interleaving for recipe trees
We interleave RecipeSteps underRecipes so a single split holds the entire recipe + steps + ingredient bindings. This keeps the common "render one recipe" read to one server hop and avoids cross-split joins.
- Parent key: recipe_id (UUIDv7, time-ordered)
- Child rows colocated; reads are single-split when within one recipe
- Cascade delete handles tombstoning when a recipe is retracted
2. Secondary indexes and STORING clauses
Lookup paths for author,tag, andcreated_at use NULL_FILTERED secondary indexes with STORING clauses on the columns the listing UI needs, so the index alone satisfies the read without a base-table seek.
CREATE NULL_FILTERED INDEX RecipesByAuthor ON Recipes(author_id, created_at DESC) STORING (title, cover_image_url, slug); CREATE NULL_FILTERED INDEX RecipesByTag ON RecipeTags(tag, created_at DESC), INTERLEAVE IN Recipes;
3. Read patterns and staleness
Listing endpoints use bounded staleness reads(10s) routed to the nearest replica, cutting median latency by roughly 60% versus strong reads. Mutating paths (publish, edit, delete) use read-write transactions against the leader to preserve external consistency.