Recently I reviewed a piece of infrastructure code written by another engineer on our platform team. The implementation itself was good. It was clean, structured, and clearly thought through. The engineer had designed the system in a way that allowed a high degree of flexibility so that different configurations could be defined through variables. From a software engineering perspective, this was a solid approach. Flexible systems are often considered good design because they can adapt to many situations and avoid making assumptions too early. However, as I looked at the design more closely, something about it felt wrong. The issue was not with the code itself, but with the interface it created for the platform. That moment highlighted an important distinction that is easy to miss: the difference between building libraries and building platforms.

Engineers are generally trained to value flexibility. When writing reusable code we try to avoid hard-coding decisions. We introduce configuration, parameters, and abstraction so the same component can support many different use cases. This instinct is often correct when building libraries or shared frameworks because those pieces of software are meant to be reused in many contexts. Over time this mindset becomes part of how engineers evaluate good design. Systems that are flexible feel elegant and adaptable. They appear future proof because they can accommodate scenarios that have not yet appeared. Giving users the ability to shape the system can feel empowering and responsible, as though the system is prepared for whatever the future may bring.

“Flexibility feels good today, but it often becomes technical debt tomorrow.”

Platforms operate under a different set of constraints. While libraries attempt to maximise flexibility, platforms exist to minimise decisions. The purpose of a platform is not to expose every capability of the underlying infrastructure, but to encode architectural decisions once so that every team does not need to rediscover them independently. A good platform reduces cognitive load. It provides a paved road where the common path is clear and easy to follow. When too many configuration options are exposed, something subtle begins to happen over time. Different teams start to shape the system in slightly different ways based on their immediate needs and preferences. Each variation may seem small and reasonable in isolation, but those variations accumulate. Systems that were originally meant to behave consistently begin to drift apart, and what once looked like flexibility gradually becomes inconsistency.

“Platforms should optimise for the average case, not the maximum flexibility.”

The long term cost of this kind of flexibility is often operational complexity. When infrastructure allows many possible shapes, environments begin to evolve in ways that are difficult to predict. Automation must handle a growing number of variations. Operational knowledge fragments because each environment behaves slightly differently. Tasks that should be routine, such as upgrades or debugging, become more complicated because assumptions about the system no longer hold universally. Flexibility can feel helpful in the moment because it solves an immediate problem, but over time it often becomes an invisible burden that the organisation must continually manage. Platforms therefore tend to optimise for the opposite outcome: a smaller number of well understood system shapes that behave consistently across environments.

“Flexibility in platform interfaces becomes operational complexity later.”

Another way to think about this distinction is through the lens of intent versus mechanism. When users are given many configuration options, they are effectively describing the mechanics of how a system should be built. They are making architectural decisions themselves, often without realising it. A well designed platform tries to reverse that relationship. Instead of asking users to define the mechanics, the platform allows them to express intent while the platform encodes the mechanisms internally. The user communicates what they need, and the platform determines how that need should be implemented. This approach removes many small infrastructure decisions from individual teams and centralises them within the platform, where they can be applied consistently and improved over time.

“Platforms should make the right thing easy and the wrong thing impossible.”

The most interesting part of this experience was not the technical design but the conversation around it. The engineer who wrote the system was capable and thoughtful, and the flexibility in the design was not a mistake. It was the natural outcome of applying good software engineering instincts to infrastructure code. The challenge was recognising that those instincts, while valuable, sometimes conflict with the goals of platform design. Libraries aim to support many possibilities, while platforms aim to guide behaviour and reduce variation. In the end the lesson was simple but important. Good platforms often do something that feels counterintuitive to engineers: they remove choices. Not because engineers cannot make good decisions, but because systems become easier to operate when the number of decisions is small and the architecture remains consistent.

“In engineering, simplicity is a feature, not a lack of effort. Every ‘hook’ you add is a debt your future self has to pay. Before you build a bridge to a place no one is going yet, just make sure the road you’re on today is paved.”