Systems Thinking Lab Newsletter — Service, Worker, Key-Value, Relational DB

Should you build it?

The weekly letter from Systems Thinking Lab: one system-design teardown framed through the seven building blocks.


Here is a story that is playing out on teams everywhere right now. A junior engineer ships a payment system in one afternoon. Stripe, Postgres, Redis, a job queue, a webhook handler. The whole thing, before the day is out.

In 2019 that was a quarter of work. Three engineers. A vendor bake-off. A wiki page arguing about whether you really needed Kafka.

The afternoon version worked in the demo. Two weeks later it was paging someone at 2 AM.

Here is what happened. The junior engineer opened Claude Code and described the app. Claude wired up Stripe for payments, Postgres for orders, Redis for sessions, BullMQ for background jobs, and an SQS queue to fan out webhooks. Every piece connected. The checkout button worked. The receipt arrived. The demo was clean.

Then real traffic arrived. The receipt email went out on the same synchronous path as the payment, so when the email provider had a slow afternoon, checkout requests hung waiting on it and timed out. Users saw a spinner, gave up, and hit Buy again. Some of them were charged twice. None of this showed up in the demo. All of it showed up in production.

The code was not the problem. The code was excellent. Claude does not write sloppy code. The problem was that nobody asked whether each tool was the right primitive for the job it was doing, or whether five tools were even needed.

Here is the shift, and it is the whole point. In 2019 the bottleneck was building. Could you wire up the payment processor at all? Could you get the queue running? The work was in the assembly.

In 2026 the assembly is free. Claude does it in one session. The bottleneck moved upstream, to a question that has no technical answer: should this exist at all, and if it should, what is it actually made of?

Tools are not the unit of design. There are seven primitives underneath every system you have ever used. Stripe is an External Service. Redis is a Key-Value Store. SQS is a Queue. The job runner is a Worker. When you name the tool, you have named a brand. When you name the primitive, you have named a decision: who waits, what fails, when it runs.

This is also why the AI-native patterns are less new than they look. An LLM shows up in your architecture as an External Service, the same slot Stripe occupies. RAG, the thing every team is rushing to build, is a Vector Database holding embeddings, a File Store holding the source documents, and a Service tying them to the model. Three primitives you already know, in a configuration that was uncommon two years ago. The names are new. The shapes are not.

Pick the wrong primitive for the access pattern and adding more tools does not save you. It buries the mistake under more wiring.

The most common wrong move in 2026 is the easy one. When building costs nothing, every instinct says reach for a new thing. Need a cache? Add Redis. Need search? Add a vector database. Need a queue? Add SQS. Each addition feels like progress because it compiles and it demos.

The senior engineer's move is the opposite. Before adding anything, the senior engineer asks one question: which of the seven am I already using, and does one of them already cover this? Most of the time one does. The junior engineer ends up with five tools. The senior engineer ends up with the same job done by two primitives they already had, and a system with half the moving parts to fail.

Restraint became the scarce skill. Not because building is hard. Because building is now so easy that the only thing standing between you and a sprawling, fragile system is the discipline to not add the next thing.

In Course 1 I teach exactly seven primitives, and the fixed count is not a limitation I apologize for. It is the entire point. When the menu is short, you are forced to choose carefully every single time. You cannot hide a bad decision behind a new tool, because there is no new tool to reach for. There are seven. You compose them.

AI did not make engineers obsolete. It made the assembly free and moved all the value to the judgment. You do not win by wiring up more. You win by knowing what you are already holding.

P.S. The hardest part is no longer wiring the tools together. It is choosing which primitive each job actually needs. I wrote up the decision framework I use for exactly that: systemthinkinglab.ai/learn/building-blocks/decision-framework/