Skip to content

Archive

Software Architecture

9 articles
Software Engineering 11 Sep 2026 9 min read

Stable Dependencies Principle: Point Toward Stability

Stable Dependencies Principle: Point Toward Stability A dependency graph is not only a map of which component calls which other component. Its direction also determines which parts of a system can change independently. Consider a reporting component used by ten other components. Many callers depend on it, so changing its public contract can require coordinated work across the codebase. That reporting component has become relatively stable: not necessarily because its code rarely changes, but because many other components constrain how freely its contract can change.

Software Engineering 10 Sep 2026 11 min read

Tolerant Reader Pattern for Evolving Contracts

Tolerant Reader Pattern for Evolving Contracts A producer adds an optional field to a response. No existing meaning changed, yet an older consumer starts rejecting every message because its parser expected exactly five fields. The producer made a seemingly compatible change, but the consumer had quietly coupled itself to details it never used. The Tolerant Reader pattern addresses that problem from the consumer side. A tolerant reader describes and validates the information it actually depends on while allowing unrelated parts of an incoming representation to vary. Used carefully, this makes contracts easier to evolve without turning validation into guesswork.

Software Engineering 10 Sep 2026 8 min read

Saga Pattern for Multi-Step Workflows

Saga Pattern for Multi-Step Workflows A workflow reserves inventory, charges a payment, and schedules delivery. Each step is handled by a different component with its own state. The inventory reservation succeeds, but payment fails. What should the system do with the reservation that already committed? A single database transaction can’t usually roll back work that has already been committed by independent components. The saga pattern handles this kind of workflow by treating it as a sequence of local transactions. When a later step fails, the workflow runs explicit compensating actions for earlier steps where business reversal is possible.

Software Engineering 10 Sep 2026 10 min read

Designing Graceful Degradation for Partial Failures

Designing Graceful Degradation for Partial Failures A page needs product details, recommendations, reviews, and delivery estimates. The product service is healthy, but the recommendation service times out. Should the whole page fail? Sometimes yes. If the missing dependency is required to produce a correct result, failing the operation is the right behavior. But when the missing part is genuinely optional, turning one local failure into a complete outage throws away useful work.

Software Engineering 09 Sep 2026 9 min read

Transactional Outbox for Reliable Message Publishing

Transactional Outbox for Reliable Message Publishing A common service operation has to do two things: change its own data and tell another part of the system what happened. For example, an order service may mark an order as paid and publish an OrderPaid message. The awkward part is that the database and message broker usually have separate commit mechanisms. If the service updates the database and then publishes, it can crash between those steps. If it publishes first, the database update can fail afterward. Either order can leave the two systems disagreeing about what happened.

Software Engineering 09 Sep 2026 9 min read

Building a Walking Skeleton Before Filling In the System

A team can make steady progress inside individual components and still discover late that the system does not work as a whole. The application starts differently in production, two modules disagree about a contract, a deployment is missing configuration, or the real request path was never exercised until several weeks of work depended on it. A walking skeleton is a small, working path through the system that connects the important architectural pieces before those pieces contain much functionality. It does not prove that the product is complete. It proves that a thin version of the system can travel from an external entry point, through the chosen boundaries, to an observable result.

Software Engineering 08 Sep 2026 9 min read

Enforcing Architecture with Fitness Functions

A team can agree on a sensible architecture and still watch it erode one small change at a time. A developer imports an internal module because it is convenient. Another adds a direct dependency across layers. Months later, the diagram still shows clean boundaries, but the code no longer follows them. Code review can catch these changes, but reviewers must remember every architectural rule and notice every violation. For properties that matter repeatedly, memory is a weak enforcement mechanism.

Software Engineering 04 Sep 2026 10 min read

Designing for Reversible Decisions

Software teams make decisions with incomplete information. A library looks suitable until production traffic exposes a limitation. A pricing rule changes after customers use it. A component boundary that seemed natural becomes awkward when a new workflow arrives. The problem is not that developers sometimes choose incorrectly. The harder problem is making an uncertain choice so expensive to change that the system must live with it long after the assumptions behind it have failed.

Software Engineering 04 Sep 2026 10 min read

Designing Failure Containment Boundaries

A component fails. Soon unrelated requests become slow, worker queues stop moving, and healthy features begin returning errors. The original defect may be small, but the system has allowed its effects to spread. Failure containment is the design practice of limiting how far a fault can propagate. The goal is not to prevent every failure. That is unrealistic. The goal is to make a local failure stay local enough that the rest of the system can continue useful work or fail in a controlled way.