Skip to content

Archive

Architecture

16 articles
Software Engineering 10 Sep 2026 10 min read

Reconciliation Loops for Self-Healing Systems

Reconciliation Loops for Self-Healing Systems A one-shot operation works well when every step succeeds. Real systems are less cooperative. A process crashes after creating half its resources, an external API times out after accepting a request, an operator changes something manually, or a dependency becomes unavailable and recovers later. If correctness depends on one command completing perfectly, every interruption creates another recovery path to design and operate. A reconciliation loop uses a different model. Instead of saying, “perform these steps once,” the system repeatedly asks, “what should be true, what is true now, and what is the smallest safe action that moves reality toward the desired state?” That shift is useful for controllers, background jobs, provisioning systems, synchronizers, and any workflow where state can drift after the initial operation.

Python 09 Sep 2026 11 min read

Manage Subinterpreters Directly with Python 3.14

Python 3.14 gives application code a new way to work directly with multiple interpreters in one process. The concurrent.interpreters module exposes a high-level API for creating interpreters, running code inside them, and communicating through cross-interpreter queues. It sits below InterpreterPoolExecutor: instead of submitting independent jobs to a ready-made pool, you own the interpreter lifecycle and decide how work reaches each isolated execution context. That extra control is useful, but it also removes several conveniences an executor normally provides. A subinterpreter is not a lightweight thread with shared globals, and creating one does not automatically create concurrency.

Software Engineering 09 Sep 2026 8 min read

Information Hiding: Design Modules Around Decisions

A module can have a tidy directory, a small public API, and still be difficult to change. The problem often appears when callers know details that should have remained private: how an identifier is formatted, which algorithm selects a price, or which fields must be updated together. When those details change, callers change with them. Information hiding is a design principle for reducing that coupling. The idea is simple: identify a design decision that may change, place it behind a module boundary, and expose the capability callers need rather than the decision’s internal details.

Software Engineering 09 Sep 2026 8 min read

Dependency Inversion Is About Source Code Direction

A business rule often starts simple and then becomes tied to a database client, email library, payment SDK, filesystem API, or framework object. The code still works, but changing the technical detail now forces changes into the code that expresses the business decision. Dependency inversion addresses this coupling. Its central idea is easy to miss: the important question is not merely whether an interface exists. The important question is which code defines the abstraction and which code depends on it.

Software Engineering 09 Sep 2026 9 min read

Containing Failures with Bulkheads

A service can fail even when most of its dependencies are healthy. One slow dependency may occupy every worker, connection, or concurrency slot until unrelated requests can no longer make progress. This is a resource-isolation problem. The dependency failure matters, but the larger outage happens because the system lets one workload consume capacity that other workloads also need. A bulkhead limits that sharing. It gives a workload a bounded resource budget so trouble in one area is less able to exhaust resources needed elsewhere. This article explains the mental model, shows where bulkheads help, and covers the trade-offs that make isolation useful rather than arbitrary.

Software Engineering 05 Sep 2026 9 min read

Replacing Systems in Slices with the Strangler Pattern

A system can be difficult to change without being possible to replace in one safe step. The old application may serve real traffic, contain years of business rules, and depend on behavior that nobody has fully documented. A complete rewrite asks the team to reproduce all of that correctly before users receive any value from the new system. The strangler pattern takes a different approach: replace the system one well-defined slice at a time while the old and new implementations coexist.

Software Engineering 05 Sep 2026 9 min read

Protecting Your Model with an Anti-Corruption Layer

Integrating another system often starts with a small amount of mapping code. Then its field names appear in business logic. Its status values enter conditionals. Its error codes shape application decisions. Months later, changing providers or even upgrading the integration requires edits across the codebase. The problem is not simply that the application has an external dependency. The deeper problem is that the external system’s model has become part of the application’s own model.

Software Engineering 05 Sep 2026 10 min read

Ports and Adapters for Testable Application Boundaries

A business rule often begins as a few lines of code and gradually becomes entangled with everything around it. A pricing decision reads directly from a database. An order workflow calls a payment SDK from the middle of its logic. Tests need a web server, network access, and several configuration files just to exercise one decision. The problem is not that databases, frameworks, or SDKs are bad. The problem is that application decisions have become dependent on details that change for different reasons.

Software Engineering 03 Sep 2026 7 min read

Replacing Legacy Systems with the Strangler Pattern

Replacing a large legacy system in one release is attractive on a diagram and dangerous in practice. The old system usually contains years of behaviour, undocumented edge cases, operational knowledge, and integrations that are difficult to reproduce all at once. The strangler pattern takes a different approach: place a boundary in front of the existing system, move one capability at a time to a new implementation, and gradually reduce the responsibilities of the old system until it can be retired.

Software Engineering 03 Sep 2026 10 min read

Dependency Injection Without a Container

Dependency injection is often introduced together with a framework or container. That can make a simple design idea look like infrastructure: register services, configure scopes, add annotations, and ask a runtime to assemble an object graph. The underlying technique is smaller. A component receives the collaborators it needs instead of constructing or locating them itself. Another part of the program decides which implementations to supply. For many applications, ordinary constructors and functions are enough. Manual dependency injection keeps object creation visible, makes required dependencies explicit, and avoids coupling application logic to a container API. A container can still be useful when the object graph becomes large or a framework owns object creation, but it is not a prerequisite for dependency injection.

Software Engineering 03 Sep 2026 6 min read

Branch by Abstraction for Incremental Change

Large replacements are tempting because they promise a clean boundary between the old design and the new one. In practice, a long-running replacement branch accumulates integration risk while the main codebase continues to change. Branch by abstraction offers a different approach. Instead of separating the work primarily with a source-control branch, engineers introduce an abstraction around the behaviour being replaced. The old implementation remains usable while a new implementation is developed and adopted behind the same boundary.

Software Engineering 02 Sep 2026 5 min read

Architecture Decision Records That Stay Useful

Software systems accumulate decisions that are obvious at the time and mysterious six months later. A database was chosen for a reason, a synchronous call became asynchronous for a reason, and a service boundary exists because some trade-off mattered. Architecture Decision Records, or ADRs, preserve that reasoning in small documents close to the code. Record decisions, not meetings An ADR should answer a future engineer’s practical questions: What problem were we solving? What constraints mattered? What did we decide? Which alternatives were considered? What consequences did we accept? Has this decision been replaced? It does not need to reproduce a design meeting transcript.

Software Engineering 01 Sep 2026 3 min read

Use the Strangler Fig Pattern for Incremental System Modernization

Large rewrites concentrate technical and delivery risk. Teams can spend months reproducing existing behavior before users receive any benefit, while the original system continues to change. The strangler fig pattern takes a different approach: replace capabilities incrementally and route traffic to the new implementation as each slice becomes ready. Choose a bounded slice Start with a capability that has a clear input, output, and ownership boundary. Good first candidates are important enough to validate the migration approach but not so central that every subsystem must move at once.

Web Development 01 Sep 2026 5 min read

Feature Flags Without Long-Lived Technical Debt

Feature flags decouple code deployment from feature release. A team can deploy dormant code, enable it for internal users, roll it out gradually, and disable it without rebuilding the application. The cost is hidden control flow. Every long-lived flag creates another possible system configuration, and interacting flags multiply those configurations quickly. The engineering goal is therefore not “use flags everywhere.” It is to make each flag temporary, observable, and owned.

Software Engineering 01 Sep 2026 5 min read

Evolving APIs Without Breaking Clients

An API is not only an HTTP path or function signature. It is a contract about syntax, semantics, timing, errors, ordering, defaults, and lifecycle. Breaking changes often happen because a server remains syntactically compatible while changing one of those less-visible assumptions. Safe API evolution starts by identifying what clients can reasonably depend on and designing changes that allow old and new versions to coexist. Compatibility has multiple dimensions A change can preserve JSON shape and still break clients.

Cloud Computing 01 Sep 2026 5 min read

Designing Stateless Web Services for Horizontal Scaling

Horizontal scaling adds application replicas instead of making one machine larger. The load balancer can send each request to any healthy instance, which only works reliably when instances do not depend on unique local state. “Stateless” does not mean the application has no state. It means durable or shared state lives outside an individual process so any replica can continue serving the workload. Identify hidden local state A service may appear stateless while depending on: