{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiedxbrnlhmw52kjckt7owlvxwkf7ckqbzuchfpebj75d6uulbezxu",
    "uri": "at://did:plc:5sgu76a53rz3n6unbykmovqy/app.bsky.feed.post/3mbng3em4c672"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreic24aw6acspok3dolrb2onk2fflxei3wod4v46fkfcgl6iooirrgq"
    },
    "mimeType": "image/jpeg",
    "size": 56824
  },
  "description": "Software has a reputation for being forgiving, something that is easy to change, easy to fix, and easy to reshape once we finally understand the problem we were supposed to be solving. That reputation is not entirely wrong, but it only holds at very small scales and only for a short while.",
  "path": "/software-is-not-flexible/",
  "publishedAt": "2026-01-05T02:42:25.000Z",
  "site": "https://sahilkapoor.com",
  "tags": [
    "Redis",
    "SQL",
    "Strangler Fig"
  ],
  "textContent": "We’ve been misled by the word ** _soft_**.\n\n_Software_ has earned a strange reputation over the years. Not just for being powerful, but for being forgiving. Easy to bend. Easy to revise. Easy to clean up once the real requirements finally become clear. That belief doesn’t usually come from engineers. In most teams, it is reinforced by product timelines, business pressure, and the comfort of knowing that nothing ships in steel or concrete. Code feels negotiable. Mistakes feel reversible.\n\nEarly in a project, code behaves like **Lego** blocks. You snap things together, pull them apart, rebuild the castle into a spaceship, and nothing breaks in any visible way. If a decision turns out to be wrong, you patch around it and move on. Compared to steel, concrete, or wiring, software feels forgiving, almost indulgent of experimentation.\n\nAs a codebase grows, services multiply, more developers contribute code, and business logic keeps getting layered in, it starts to behave more like **wet concrete**. Early on, you can still push it around, move walls, redraw boundaries, and smooth over rough edges. But once the system is coordinating across services, holding persistent data, serving real users, and supporting revenue, it begins to set. From that point on, change no longer feels like editing. It feels like demolition.\n\nMost teams don’t notice the moment this shift happens. They notice it later, when things that used to be easy start taking longer, and when _small changes begin to carry an uncomfortable amount of risk._\n\nThe Lego mindset is part of how teams get there. It shows up as small technical shortcuts that feel harmless at the time, like a missed cache key in Redis that quietly sends traffic back to**** SQL Server, or a background job that bypasses the domain layer because it is “just internal.” If you stack bricks just because they fit, you don’t end up with flexibility. You end up with a structure that works right up until it doesn’t. One edge case, one traffic spike, or one new requirement later, the wobble starts.\n\n> _Optimising for speed of assembly is not the same as optimising for survival under load._\n\nReal engineering is about whether the internal bonds hold when the system is stressed, not about how fast you can put something together. The Lego approach optimises for getting to “done,” but it does very little to optimise for load, failure modes, or long-term change.\n\n## The Double Standard\n\nMost systems don’t fall apart when they are failing. They fall apart right after they start working.\n\nOnce something is live and people depend on it, the definition of risk quietly shifts. Shipping fast still matters, but breaking things suddenly matters more. So teams start making small compromises to keep momentum going. They skip an abstraction to hit a deadline. They hardcode a path because it is faster than untangling the model. They promise themselves they will clean it up later, when things are calmer.\n\n_Remember, that calm never comes._\n\nIn every other discipline, scale brings more rigor, not less. Bridges do not loosen their standards as traffic increases. Aviation systems do not get more casual as routes expand. Software, somehow, is treated as the exception. We justify this because we can’t see the cracks. There is no sagging beam or visible fracture. Everything looks fine until it isn’t, so we tell ourselves the risk is abstract, manageable, and something we can deal with later.\n\nWe would never accept that logic anywhere else.\n\nImagine a pilot saying:\n\n> _“We’re behind schedule. Let’s skip the pre-flight check. We’ll just push an engine patch mid-air if things start smoking.”_\n\nOr a surgeon saying:\n\n> _“I’m skipping the hand-washing to save time. We can treat the sepsis during the next sprint.”_\n\nOr a civil engineer saying:\n\n> _“The foundation is cracking, but the client needs the penthouse finished by Friday. We’ll refactor the basement once the building is full of people.”_\n\nIn those fields, discipline is the price of entry. In software, we still talk about it as if it were a nice-to-have.\n\nOnce users depend on a behavior, a temporary hack quietly stops being temporary. It becomes an **undocumented contract**.\n\n## The Physics of Slowdown\n\nOnce those contracts exist, the system starts to change how it behaves.\n\nThis is where _cohesion_ and _coupling_ stop being abstract ideas and start showing up in daily work. Responsibilities that belong together end up scattered. A change in one place quietly reaches into others. Code stops reflecting intent and starts reflecting everything it has ever had to accommodate.\n\nYou see the effects long before anyone names the cause. Engineers hesitate before making small changes. Deployments get delayed, not because the change is large, but because nobody is confident about what else might be affected.\n\nAt first, this friction is easy to ignore. Then it compounds.\n\nFeatures that once took days start taking weeks. Bug fixes trigger regressions. Releases stop feeling routine and start feeling dangerous. The **Total Cost of Ownership** does not rise gradually. It jumps.\n\nWhen teams say they have slowed down, this is usually why. Not because engineers suddenly care too much about quality, but because the system has lost its ability to absorb change.\n\nOther industries never had the luxury of pretending otherwise. A sloppy manufacturing supply chain can bankrupt a company in a quarter. A loose telecom protocol can take an entire network down. Poorly planned urban infrastructure costs lives.\n\n> **In those fields, technical debt isn’t a metaphor. It’s a suicide note.**\n\nSoftware is the only place where we’ve convinced ourselves that the bill can be outrun indefinitely.\n\n## Knowing When to Step Back\n\nThe instinct to defer discipline usually comes from good intent, not ignorance. Lean Startup thinking pushed back, rightly, against over-engineering before product market fit. Many teams wasted time building futures that never arrived.\n\nThe problem begins when that mindset outlives its usefulness and teams fail to recognise the inflection point.\n\nOnce a product works,  _later rarely comes_. Usage grows, data accumulates, teams expand, and the system quietly shifts from experiment to infrastructure. At that point, treating discipline as optional stops being pragmatic.\n\nThis is the moment where product and business leadership matters most. Speed does not come from ignoring technical limits. It comes from knowing when the system needs time, not features.\n\nSlowing down here does not mean stopping. Refactoring and rebuilding are not aesthetic exercises. They are strategic interventions to restore the system’s ability to change. Sometimes that means untangling a dependency. Sometimes it means rebuilding a critical path.\n\nThe only sustainable approach is incremental change. Patterns like the Strangler Fig exist because hardened systems can’t be reset, only replaced piece by piece.\n\nKnowing when to listen to these signals is what keeps speed, reliability, and trust intact as systems grow.",
  "title": "Software Is Not Flexible. It Hardens as It Grows",
  "updatedAt": "2026-05-13T17:17:18.257Z"
}