Getting the Primitives Right

Why does adding a new feature become so difficult as a system grows?

Systems rarely begin that way. At first, there is little code and each feature has a clear place. Then the system grows. Adding one feature means changing many parts of the code. A small change can break something somewhere else. The team spends more time working around the system than building the feature.

We often call this complexity or technical debt. Those words describe the problem, but they do not explain why it happened. Sometimes the system was simply built around the wrong ideas.

This is where the advice to “get the primitives right” comes from. A primitive is not simply a small part of a system. It is one of the basic ideas or capabilities the rest of the system builds on. In a UI framework, state can be a primitive. In a database, it might be a transaction. In a payment system, it might be an account and a record of money moving in or out.

Good primitives give new features a clear place in the system. Weak ones force each feature to work around what is already there. Their cost often appears when you try to build the next feature.

The visible thing is rarely the primitive#

The first version of a product pushes you to model what’s on the screen. In a payment system, there is a balance, so you store that number and update it whenever money moves.

This feels reasonable at first. But the balance is only the result. It does not tell you what happened.

A payment, refund, fee, and transfer can all change the same balance. Each one means something different and should leave a record. If the system models only the number, each new feature has to invent its own way to change it. The system slowly fills with different ways of doing the same thing.

Correctness should live in the primitive#

A primitive should not just let the system do something. It should also protect the rules that must never be broken.

In a payment system, money should not appear or disappear without a record. Each feature can check this rule itself, or the system can check it in one place.

If every feature has to remember, someone will eventually forget. When the check is part of the primitive, every feature follows the same rule automatically. A strong primitive makes the right thing easier to do and the wrong thing harder.

Good primitives support more than one feature#

The real test of a primitive is what you can build from it later.

A refund should use the same accounts and records as a payment. It should not need a separate way to track money.

With good primitives, new features reuse ideas the system already understands instead of creating their own fields, rules, and ways of doing the same work.

Strong primitives also make the system easier to explain. A balance tells you the current number. A ledger shows how it got there.

Mutable balanceLedger
Current balance: $130Opening balance: $100
Why? UnknownPayment: +$50
Refund: −$20
Current balance: $130

That history helps with debugging, support, and understanding how the system behaves over time.

Primitives are often discovered as the system grows#

You rarely know the right primitives on the first try. That is normal. A simple model may be enough for the first version, and a special case may really be a special case.

The warning sign is repetition. Several features solve the same problem in different ways, or each one has to remember the same rule. That repeated idea may be the primitive the system is missing.

This is not the same as trying to design for every possible future. You are not guessing what might be useful. You are looking at real features and noticing what they share.

The goal is not the most general model. It is a small set of useful ideas that match the problem, protect its rules, and continue to work as the system grows.

Features describe today. Primitives shape tomorrow.#

A weak primitive can support the current feature while making the next one awkward. The difference becomes visible in the special cases and workarounds that collect around old decisions.

Getting the primitives right is not about predicting every future requirement. It is about building a foundation that lets tomorrow’s features extend the system rather than fight it.