Designing cloud foundations the next engineer can extend
Most cloud foundations are judged on whether the first deployment works. It is the easiest question to answer and the least useful one, because almost any competent design passes it.
The question that decides whether the work was good is what happens in the days, weeks, and months after it has been handed off, when someone who was in none of the original conversations needs to maintain, or worse, to change something the design did not anticipate. They will either extend what you built or route around it. Routing around it is the real failure, and it never appears in a status report.
Everything below is written from that vantage point.
What I look for before choosing an architecture
Four things, and only one of them is technical.
Who owns this after I stop touching it, and how much context will they have? The honest answer is usually: someone under time pressure, at an inconvenient hour, with none of the reasoning that produced the design. That person is who the architecture is actually for. Designing for the version of yourself who already understands it is the most common mistake I see, and it is invisible while you are still there.
Which parts will need to remain flexible, and which are expected to remain permanent? It’s natural to build things that work in isolation and with expected values, but difficult to think of how things might need to adapt in the future. Asking the question out loud and explicitly, before the diagram, surfaces the issues while still cheap. A design the on-call rotation cannot reason about at three in the morning will be worked around, and the workarounds quietly become the real architecture.
What the team can operate, rather than what seems like an improvement. The best tool is frequently not the best tool for a given team. I have chosen the toolchain a team already knew, rather than the one I would have picked for myself, and I would make that trade again. The learning curve on unfamiliar tools can be just as detrimental as a bug in the program.
Know when to hold em, know when to refactor. Knowing when to extend something and when to rebuild it instead. The signal I trust is whether I can fully reason about what it does and whether the next person can do the same, in addition to improving maintenance. If I am maintaining an unpredictable system, every change I make is a guess costing money and likely more with no concrete resolution. Rebuilding is expensive; guessing is more expensive, later, and to somebody else. Documentation is fantastic. Clean, understandable, maintainable code that doesn’t need documentation to explain tends to be better than documentation alone.
The tradeoffs that only appear later
The bill for an architectural decision almost always arrives later, the first time someone needs to do something the design did not anticipate. This is commonly referred to as technical debt, and it builds quickly.
Make things robust where failure would be costly; keep them simple where it’s safe to do so. Production databases should always have automated backups, multi-zone failover, encryption at rest, and protection against accidental deletion. Test and training environments are a different story: they usually don’t need the full set of production features, and stripping out extras can make them easier and cheaper to run. But sometimes you really do want test to be a full replica of production, and that’s worth considering too.
Strong security through automatically managed, regularly rotated credentials. It is well understood that credentials should be rotated; following the platform’s best practices keeps everything secure and ensures the next engineer has a documented, compliant, and secure way to maintain the application in that state.
Ownership and handoff change the design
The difference between an installation and a platform is whether the second instance is cheaper than the first. That property has to be designed in before there is a second customer to justify it, which means arguing for it on faith. Two things make it real.
Enforce conventions in the tooling. A tag standard that lives in documentation is often overlooked, varies in casing and sometimes spelling when it gets to deployment; the same standard, gated so that a typo fails deployment rather than being left out, prevents issues instead of creating them. Consistency is achieved by adhering to standards.
The finance team asked for tagging so their billing reports could be cleanly separated whenever someone queried them. I took it a step further and created rules so that anything not tagged correctly would not deploy, preventing anything from drifting out of the billing calculations.
Make every stage inspectable. Anything hidden from view or obscured gets overlooked or bypassed, and that is usually where problems start. Without logical separation, maintenance becomes difficult or impossible.
What it comes down to
A foundation that works on day one has only started. It is finished when someone who was not there can look at it, understand why it is shaped the way it is, and change it effectively without fear.
Most of the decisions above cost slightly more up front and buy exactly that. When I evaluate an architecture now, mine or anyone else's, the first question I ask is whether the next person will extend it or route around it.