← Wiki index← Home
Table of contents

Working principles

These are five habits I try to stick to when designing services, reviewing pull requests, debugging production issues, and working with other engineers.

1. Fix the problem at the decision point

When a bug shows up in production, the tempting fix is to add a retry loop, a null check, or a wrapper layer at the end of the call chain. Most of the time, that just hides the real problem and makes the system harder to reason about six months later.

Before writing a patch, trace the behavior back to the exact line of code, SQL query, or routing rule where the system took the wrong turn. Fixing it at the source keeps the diff small and prevents cascading workarounds.

2. Treat operations as part of the design

A service isn’t ready for production just because the happy-path unit tests pass. While designing an API or background worker, we should already know:

If we can’t answer those four questions during design review, the feature isn’t ready to ship. (See Spring Boot on ROSA and Observability and collaboration.)

3. Prefer boring, explicit interfaces

Clever reflection tricks, custom framework wrappers, and undocumented conventions feel productive for the person who wrote them and painful for everyone who maintains them later.

Standard REST or GraphQL contracts, straightforward SQL, explicit timeouts, and declarative GitOps manifests age much better than bespoke abstractions. Fewer moving parts mean fewer weird failure modes under load.

4. Leave context for the next engineer

Code gets written once and read hundreds of times—often by a teammate debugging an incident under time pressure.

5. Name the trade-offs out loud

Every architecture choice trades one problem for another—simpler deployment now vs. harder multi-region scaling later, strict consistency vs. lower latency, building in-house vs. adopting a managed tool.

When making a technical call, I like to write down what we are optimizing for, what risk we are accepting, and what threshold would make us revisit the decision later (for example: “A single Aurora writer with read replicas handles our current load; revisit sharding or caching if sustained writes pass 3,000/sec”). Naming trade-offs openly keeps architecture discussions grounded in numbers instead of opinions.

Type a topic, technology, or question to search...
flappy-pod // prod-us-east-1
SCORE: 0BEST: 0