Designing Defaults That Fail Safely
A practical reflection on choosing defaults that protect users and systems when configuration, rollout, or external dependency behavior is uncertain.
Articles
Comment organiser le code source pour qu'il survive à la croissance, aux équipes et aux changements.
Des analyses approfondies et accessibles aux débutants sur l'architecture logicielle et l'organisation du code source — des Ports & Adapters et Clean Architecture à la gestion des dépendances, aux frontières de modules et aux compromis qui sous-tendent chaque choix. Fondées sur des diagrammes, des exemples concrets et des enseignements qui s'appliquent aussi bien aux projets solo qu'aux systèmes d'entreprise.
A practical reflection on choosing defaults that protect users and systems when configuration, rollout, or external dependency behavior is uncertain.
A practical reflection on designing data contracts that are narrow, testable, and stable enough for teams to rely on.
A practical reflection on choosing simple software boundaries that make ownership, testing, and future change easier to reason about.
A practical reflection on building safe operational escape hatches that are explicit, audited, and bounded instead of hidden back doors.
A practical reflection on designing interfaces that show real system limits before users and operators have to discover them through failure.
A practical reflection on designing software around visible change patterns instead of abstract future flexibility that may never arrive.
A practical reflection on why software boundaries become clearer when teams anchor them in examples, responsibilities, and behavior instead of only naming layers.
A practical reflection on making architecture decisions small, explicit, and revisitable so teams can learn without turning every choice into a permanent monument.
A practical reflection on designing software interfaces that keep product behavior stable while implementations change underneath.
A practical reflection on refactoring toward a clearer core: how teams can reduce coupling, protect behavior, and make the center of a codebase easier for future teammates to understand.
A practical reflection on architecture decisions as team memory: how small ADR-style notes help future teammates understand trade-offs, rejected paths, and when to revisit a choice.
A practical reflection on architecture boundaries: why teams should name ownership, data, and change patterns before reaching for frameworks, services, queues, or databases.
A practical explanation of observability as an architecture decision: why teams should design logs, metrics, traces, dashboards, and alerts into the system before production asks hard questions.
A practical explanation of the Outbox Pattern: why dual writes fail, how a transactional outbox keeps database state and events aligned, and what teams still need to handle around retries, idempotency, ordering, cleanup, and observability.
A practical explanation of service mesh trade-offs: what it centralizes, when it helps, and why teams should solve real service-to-service pain before adopting another infrastructure layer.
A beginner-friendly guide to Event Sourcing: storing facts as an append-only event history, rebuilding current state through projections, and understanding when the pattern is worth its operational cost.
A practical explanation of the Saga pattern for distributed transactions: why one database transaction stops working across services, how orchestration and choreography differ, and why compensation, observability, and idempotency matter.
A practical look at API gateway responsibilities: routing, authentication boundaries, rate limiting, request aggregation, backend-for-frontend trade-offs, failure modes, and the observability needed to keep the edge of a system understandable.
A practical guide to applying Hexagonal Architecture to one small feature: drawing the boundary, naming ports in business language, keeping adapters at the edge, testing the core, and deciding when the extra structure is worth the cost.
When services hold hands through synchronous calls, latency adds up and one slow dependency takes down checkout. A no-hype guide to event-driven architecture: sync vs async, commands vs events, what brokers really promise (at-least-once, not exactly-once), choreography vs orchestration, and exactly when NOT to reach for events.
Splitting code is the easy half — splitting data is where distributed systems humble you. A practical guide to owning data across services: why a shared database is a distributed monolith, the trade from ACID to eventual consistency, the dual-write bug and the outbox that fixes it, sagas with compensating actions, and when CQRS and event sourcing are worth their lifetime cost.
The moment a call leaves your process it can be slow, fail, or happen twice — and that is the normal case, not the exception. The resilience toolkit, explained plainly: why timeouts come first, how retries become a self-inflicted DDoS without backoff and jitter, why idempotency is the price of retrying, and how circuit breakers, bulkheads, graceful degradation, and observability keep one bad dependency from taking down everything.
The database is almost always the first thing to buckle under growth — and the first thing engineers over-engineer in a panic. A no-hype ladder for scaling the data layer: why you measure and add an index before touching hardware, how read replicas exploit the read/write asymmetry (and the replication-lag trap they bring), where caching helps and why invalidation is the hard part, and when you finally reach for partitioning and sharding — the one decision that is genuinely hard to undo.
In a monolith, debugging was almost cosy — one log file, one process, one place the truth lived. Distributed systems quietly took that away: one request now fans out across a dozen services, and when it breaks there is no single log to read. A no-hype guide to seeing your system at scale: the three pillars (metrics, logs, traces) and the question each one answers, why a single propagated trace ID is the highest-leverage habit you can adopt, how SLOs turn reliability into an error budget you can spend, and how to alert on symptoms so on-call doesn't burn out.
Microservices can create real team autonomy, but they move cost into operations, data consistency, observability, testing, and coordination. This piece asks when that cost is worth paying and when a modular monolith is the kinder architecture.
Un guide accessible et riche en exemples sur l'Hexagonal Architecture : ce que sont vraiment les ports et les adapters, la règle unique qui la fait fonctionner, et exactement quelle dose en appliquer — que vous soyez un fondateur solo ou une équipe d'entreprise.
Elles ressemblent à trois architectures rivales. En réalité, c'est la même idée — les dépendances pointent vers l'intérieur, les frameworks restent à la périphérie — dessinée de trois façons différentes. Voici ce que chacune apporte vraiment, et laquelle choisir.
Les conteneurs DI semblent magiques jusqu'à ce que vous voyiez l'idée simple qu'ils cachent : arrêtez de laisser le code créer ses propres dépendances, et passez-les plutôt de l'extérieur. Un guide depuis zéro, avec de vrais exemples et les bénéfices pour les tests.
Vos dossiers de premier niveau doivent-ils s'appeler controllers/services/models, ou orders/billing/auth ? Ce choix discret façonne silencieusement la façon dont votre codebase grandit. Un tour pratique de la structure par couche, par fonctionnalité et de la Screaming Architecture — avec les compromis à chaque taille d'entreprise.
Les microservices sont une taxe que vous payez pour la mise à l'échelle organisationnelle — pas un point de départ. Un parcours sans fioriture du monolithe au monolithe modulaire puis aux microservices, avec les signaux qui vous disent quand (et si) diviser.
Diviser le frontend en pièces déployables indépendamment peut libérer les équipes — ou vous noyer dans la complexité. Rédigé à partir de l'expérience de livraison d'une configuration Angular-host + modules React à grande échelle : quand les micro-frontends rapportent, et la facture qu'ils entraînent.
L'architecture en couches semble ordonnée au début, tandis que les vertical slices rapprochent le changement de la fonctionnalité réelle. Un regard calme sur les deux approches, leurs forces et les signaux qui disent qu'il est temps de changer.
Dependency direction is the simple team rule that says stable business ideas should not depend on volatile delivery details. This explainer uses a small release scenario to show how the rule keeps code, reviews, and team conversations calmer.
A practical explanation of eventual consistency beyond the textbook definition: what users notice, which trade-offs teams are really making, how to set expectations in the product, and how operations keeps delayed truth from becoming silent data drift.
A practical explanation of CQRS: separating commands from queries, when read and write models deserve different shapes, and how to avoid turning a useful pattern into unnecessary architecture.
A practical look at serverless architecture: what teams gain by handing infrastructure to managed platforms, what they still own, and how to decide when functions, queues, and managed services are the right trade.
A practical explanation of caching strategies: where caches help, how cache-aside, read-through, write-through, TTLs, and invalidation differ, and why stale data, stampedes, keys, and observability matter as much as speed.
A practical explanation of database sharding: what changes when one database is split into smaller partitions, when sharding is worth the operational cost, and why shard keys, hotspots, rebalancing, and observability matter.
A practical comparison of GraphQL and REST: how each shapes API contracts, frontend flexibility, caching, observability, team ownership, and the operational trade-offs behind choosing one style over the other.
A practical explanation of idempotent API design: why retries happen, how duplicate requests create risk, and how idempotency keys, stable state transitions, and clear response contracts make distributed systems calmer.
A practical explanation of rate limiting and throttling: how systems protect shared capacity, shape traffic, communicate limits clearly, and keep overload from turning into a full outage.