Note: This post is a response to a recent blog by the ‘High Priest of Architecture’ at a UK-based bank, and their loyal cronies crooning over it, plus the endless parade of ‘agile evangelists’ parroting buzzwords without ever facing reality
Move fast. Stay flexible. Let architecture emerge.
Sounds inspiring until you see what most organizations are actually doing. Somewhere along the way, agile architecture becomes agile amnesia. Big Design Up Front is replaced by Big Design Never. Chaos disguised as adaptability is now celebrated as agility.
Let me tell you what really happens.
Months are spent producing perfect architectural blueprints. Diagrams, review packs, and decision logs, while the business decides to change its course mid-cycle. Everything looks rigorous on paper, but production systems diverge completely.
Emergent design is supposed to be flexible, but without explicit guardrails, it produces redundancy, conflicts, and technical debt. One team might adopt the company’s monitoring framework, another business unit sticks with its old stack. Locally, things work, but enterprise-wide observability is lost. Architects assume ownership of their domain, but the pipe dream of enterprise coherence never materializes.
We know how feedback loops are supposed to make things better? In reality, they often don’t. Postmortems get written up in Confluence, nobody actually creates tickets, and the same outages keep happening. Deferred decisions sound smart; let’s wait until we have more context. But some things just can’t wait. Pick the wrong database or get your API contracts wrong, and the first big traffic spike turns that clever deferral into a rushed, expensive fire drill.
Extreme Programming practices, of pair programming, CI/CD, and TDD, are supposed to stop that chaos. Skip them for a tight deadline, and suddenly, subtle bugs start spreading across your microservices. Weeks later, you’re paying for technical debt that could have been prevented.
And then there’s DDD (Domain Driven Design). In theory, it promises clarity via bounded contexts, alignment with business domains, and clean boundaries. In practice, every business unit does its own thing. One team builds the Orders service in Python, another in Java, with different data models and events. Everyone thinks they own their domain, but the enterprise never lines up. APIs clash, integrations take weeks, and all that elegant theory suddenly feels like a fantasy.
Microservices are supposed to make life easier, but in practice, they can multiply headaches. Everyone celebrates autonomy, yet suddenly you have hundreds of services running across different units, each with its own way of handling authentication, logging, monitoring, and deployments. Data gets duplicated, transactions become messy, and consistency is a daily headache. What’s meant to be flexible and emergent often ends up as a fragile tangle of siloed systems, a playground for clever hacks and half-hearted compliance.
Non-functional requirements are critical, yet often ignored. Security standards exist centrally, but some units bypass them for speed. Performance testing is skipped. Integration fails. Business-unit deviations, retail versus corporate finance, make compliance a patchwork rather than a guarantee.
And it’s not just the technology. Culture kills more architecture than anything else. Shadow services crop up to bypass review, frameworks get forked because dependencies are a pain, and compliance theater becomes the norm. Teams move code to a new repository, everyone claps, but production still runs from the old one. Architects act like they own their domains, thinking they control everything, while in reality, silos and turf wars quietly grind enterprise alignment to dust.
Implementation is the acid test. ADRs are ignored, walking skeletons never reach production, CI/CD pipelines are bypassed, and feedback is documented but never acted upon. Even when architects own a domain, enterprise-level execution diverges, leaving emergent architecture theoretical.
Scaling just makes the mess worse. Suddenly, you’ve got hundreds of microservices running across different business units, each doing things its own way. Chaos testing exposes all the cracks. Failover paths that don’t actually fail gracefully, services that break in unexpected ways. What was supposed to be emergent and flexible starts to feel fragile, brittle, and expensive. You suddenly realize freedom without some guardrails is chaos wearing a fancy name.
Agile architectures work well when teams are small or bounded, decisions are made at the right time, feedback is applied rigorously, knowledge is shared, XP practices are followed, domains and bounded contexts are respected, microservices are used judiciously, NFRs and compliance are enforced, dependencies and tech debt are managed, leadership actively steers, organization politics are addressed, business-unit deviations reconciled, and implementation aligns with principles. Without this, emerging, evolving, adaptive architecture is wishful thinking.
Real agility isn’t freedom from constraints, it’s freedom within them.
Teams can experiment, but someone still has to make sure the system actually works tomorrow.