#Architecture
Software architecture defines the structural decisions that shape a system's quality attributes: performance, maintainability, and resilience. These posts present architecture patterns, framework comparisons, monolith-to-microservices migration, and the design trade-offs behind production systems.
36 posts tagged with architecture. ← All posts
The capstone — one problem, a home-timeline feed, designed the whole way through with the method from post one: clarify, estimate, contract, then high-level to deep-dive to bottleneck, naming the trade-off at every step and drawing on all seven earlier posts.
The capstone: one worked design end to end — requirements, estimation, API and data model, high-level architecture, and deep dives applying the whole series (scaling, caching, sharding, consistency, async, reliability) with explicit trade-offs.
Architecture is never finished. This post is about designing systems for the change you know is coming, guarding the characteristics you care about with automated fitness functions, and treating technical debt as an ongoing budget rather than a someday-rewrite.
Architecture is never done: evolutionary architecture and fitness functions that guard characteristics in CI, technical debt done right (deliberate vs reckless, managing the interest), and incremental strangler-fig migration instead of the doomed big rewrite.
How to communicate an architecture so it survives contact with a real team — a few living, versioned diagrams and decision records instead of a dead 200-page tome nobody opens twice.
Communicating architecture so it survives contact with a team: the C4 model's zoomable levels, diagrams-as-code that live in version control and don't rot, multiple views for multiple audiences, and just-enough living docs plus ADRs.
When REST is the wrong shape for the problem, GraphQL and gRPC each fix a different pain — and each buys that fix with a new cost you have to design around.
When REST isn't the right shape: GraphQL (client-selected fields, and its N+1 / caching / complexity costs) and gRPC (Protobuf, HTTP/2, streaming, codegen) — plus a decision framework for REST vs GraphQL vs gRPC.
The recurring structural patterns an architect actually reaches for — layered, hexagonal, DDD boundaries, CQRS, event sourcing, saga, strangler fig, and BFF — each with the problem it solves, the cost it charges, and the honest signal that you need it.
The recurring structural patterns and their costs: layered, hexagonal/ports-and-adapters and clean, DDD bounded contexts, CQRS and event sourcing (frequently over-applied), saga, and the strangler fig — apply the simplest that solves the real problem.
The core of the architect's job is not drawing boxes but making, justifying, and recording the significant, hard-to-reverse decisions a system is built on — deliberately, under uncertainty, and with the reasoning written down.
The core of the job: making and recording decisions under uncertainty — one-way vs two-way doors, structured trade-off analysis, avoiding resume-driven development, and Architecture Decision Records (ADRs) that keep the why alive.
Choosing and scaling the data layer without cargo-culting: how to pick relational versus NoSQL by access pattern, why every index is a tax on writes, and why your shard key is the highest-stakes decision you will make.
Choosing and scaling the data layer: relational vs NoSQL by access pattern, indexing (B-tree/hash/LSM), normalization vs denormalization, replication, partitioning/sharding and the shard-key decision, and the distributed-transaction trade-off.
Why the non-functional requirements — performance, scalability, availability, security, maintainability and their kin — are what your architecture is actually optimized for, how to make them measurable, and why they always trade off against one another.
The non-functional requirements that actually drive architecture: the -ilities (performance, scalability, availability, security, maintainability…), making them measurable as scenarios with numbers, and prioritizing the top few because they all trade off.
The highest-leverage tool for latency and scale — and the source of its hardest problem, invalidation. Where caches live, the patterns for filling them, how they evict, and why keeping them correct is the part that stays hard.
Caching as the highest-leverage latency tool — and its hardest problem: where caches live, the patterns (cache-aside/read-through/write-through/write-behind), eviction, and invalidation including cache stampede, penetration, and hot keys.
A trade-off-driven tour of the major ways to structure a system — monolith, modular monolith, layered, microservices, service-based, event-driven, and serverless — and how to choose one by team, scale, and organizational maturity rather than hype.
The major ways to structure a system and their trade-offs: the modular monolith (the underrated default), layered, microservices (and their heavy costs), event-driven, and serverless — chosen by team topology and scale (Conway's Law), not hype.
How to model resources as nouns, choose HTTP methods by their spec-defined semantics, return the right status codes, and decide honestly how much hypermedia your API actually needs.
Designing REST resources the right way: modeling resources as nouns, URI design, HTTP method semantics (safe vs idempotent, PUT vs PATCH), using status codes correctly, and a realistic take on the Richardson Maturity Model and HATEOAS.
How systems grow under load — vertical vs horizontal scaling, why statelessness is the real enabler, load balancing from L4 to L7, consistent hashing, read/write scaling, the scale cube, and when the honest answer is "don't scale yet."
How systems grow: vertical vs horizontal scaling, statelessness as the enabler of horizontal scale, load balancing (L4/L7, consistent hashing), read/write scaling with replicas — and knowing when not to scale.
The opening post of "The Software Architect's Path" — demystifying the role by separating what architecture actually is (the decisions that are hard to reverse) from day-to-day coding, and arguing for the hands-on architect over the ivory-tower one.
The opener to an architect series: what architecture actually is (the significant, hard-to-change decisions), the architect's real responsibilities, the hands-on architect-who-codes model vs the ivory tower, and the myths worth discarding.
The opening post of a series on designing APIs people actually enjoy using — why an API is a contract and a product, the qualities that separate a good one from a bad one, and why the contract should exist before a single line of implementation.
The opener to an API design series: an API is a contract and a product whose users are developers — the qualities that matter (consistency, evolvability, hard-to-misuse), API-first vs code-first, the interface/implementation boundary, and the paradigms you'll weigh.
A repeatable method for designing systems and acing the design interview — clarify requirements, estimate on the back of an envelope, pin down the API and data model, then work high-level to deep-dive to bottleneck, always naming the trade-off.
The opener to a system-design series: a repeatable method rather than a grab-bag of components — clarifying functional vs non-functional requirements, back-of-the-envelope estimation with the latency numbers every engineer should know, and the trade-off-driven design flow.
Deterministic rules get first refusal at zero model cost. Only the unknown cases escalate to graduated AI agents. A human approves anything that mutates.
Deterministic rules get first refusal at zero cost and still fire when the model is down; only the novel long tail escalates to graduated agents; a human approves anything that mutates. Build a ladder, not a model call.
Turning raw blocks and logs into queryable app state that survives reorgs, backfills, and finality.
Building an indexer: block ingestion, log decoding, reorg-safe writes, backfills, and serving queryable balances/history to the app.
How a rating engine turns raw usage and transactions into charges — and why the hard part is making that transformation deterministic, replayable, and idempotent.
How a rating engine turns usage/transactions into charges via pricing plans, tiers, and promos, then produces invoices and fee postings.
Why fintechs keep a transaction-grain subledger separate from the accounting general ledger, and how the posting, aggregation, and tie-out actually work.
Why fintechs keep a high-volume subledger separate from the GL, posting rules, summarization/aggregation, and period-close handoff.
Four protocols, four jobs: how tools, agent-to-agent messaging, and payment rails compose into one buying flow.
How the layers compose: MCP gives an agent tools and context; A2A lets agents talk to each other; AP2/ACP/x402 are the payment rails those agents call when money must move.
The surface a store must expose when the buyer is an AI agent, not a browser — and why it is the fintech reliability playbook wearing a new hat.
What a store must expose to sell to agents: a machine-readable product feed/catalog, agentic checkout endpoints, acceptance of delegated payment tokens, idempotency keys for retried agent calls, webhooks for async status…
How a custodian actually safekeeps client assets — account structures, the custody network, settlement instructions, and the books-and-records engine that keeps it all honest.
How a custodian holds assets in omnibus vs segregated accounts, the CSD/sub-custodian network, settlement instructions, and asset-servicing (income, proxy, tax).
The reference architecture distinguishes request-based and message-driven agent communication. For in-process orchestration, the workflow IS the broker — and A2A is just the wire format.
AgentSession is short-term memory. MemoryContextProvider + MemoryFileStore is long-term memory. Mem0 is long-term memory for serious workloads. The boundary that matters and how to implement each.
The Microsoft Agent Framework deliberately does not ship an agent registry. Here is why that is the right call, and what to build as a project-local convention when you need one.
Microsoft published a 12-chapter reference architecture for multi-agent systems and a separate framework — the Microsoft Agent Framework — to build them. Here is what the 102 Python files actually contain and how they map to the chapters.
The philosophy, trade-offs, and what we learned converting 18+ agents in 3 months.
The philosophy, trade-offs, and what we learned converting 18+ agents in 3 months. Provider abstraction as the foundation for portable agents.
Status-code-based dispatch made every worker grow a longer and longer switch. Normalising every partner-specific error into an enumerated set let the orchestration logic stop changing as new partners landed.
30 minutes on stage. The talk title looked tactical; the talk underneath was about why most microservices migrations fail and how to set up the one that doesn't.
The mental model that says no two adjacent layers share a single point of failure for the same class of attack. From TLS to OTel, the eleven layers a customer request crosses before an answer comes back.
The long-form security narrative for a multi-agent financial assistant — authentication, authorisation, tenant isolation, dual-identity audit, envelope encryption, hash-chained logs, governance, red team, BCP.
Stdlib over libraries, single binary over framework, fail-closed defaults over forgiveness. The boring-on-purpose case for choosing Go to ship a multi-agent system into a regulated environment.
Microsoft's Multi-Agent Reference Architecture in Go. Protocol, registry, bus, governance, orchestration, observability, evaluation — and how the seven hold each other up.
Google publishes a 12-pattern taxonomy for agent design. Most of them have direct corollaries in production code; one or two are best ignored. The mapping I've used.
Postgres over the latest vector DB. Go stdlib over the framework du jour. Single binary over Kubernetes operator. The choices that bore reviewers and delight on-call engineers.
The audit log isn't a side effect of the system. It's the contract you owe to regulators, customers, and your future self. Treat it as a first-class API — schema, versioning, and SLOs included.