Ways of Working
Principles and practices for how I like to operate as a Technical Lead and Solution Architect.
Technical Decision Making
Section titled “Technical Decision Making”- Document the why, not just the what. Write a short decision record for any decision that’s hard to reverse or affects multiple teams.
- Involve the people who will implement it. A decision made in isolation is a constraint imposed on others. Pull in engineers early.
- Time-box spikes. Exploratory work should have a defined timebox and a clear question it is answering.
- Default to reversible. When in doubt, choose the option that keeps options open.
Starting a Project
Section titled “Starting a Project”Sprint 0
Section titled “Sprint 0”Sprint 0 gives the team room to set up the foundations before feature work starts, without pretending that setup is feature work. By the end of it, I’d expect:
- A delivery pipeline: repository, CI/CD, environments and one-command local development, so the first feature can ship as soon as it’s built.
- A walking skeleton (see below), which is the main technical output.
- An initial architecture: a placeholder that’s good enough to start from, with the key decisions recorded and simple context and container diagrams (see Avoid Paralysis by Analysis).
- Enough shaped backlog for the first real sprints.
It isn’t big design up front, it isn’t the place to build infrastructure for scale you don’t have yet, and it shouldn’t be a feature sprint in disguise. I’m fairly relaxed about the timebox. With two-week sprints, one to two sprints is reasonable, because the same period usually includes workshops on backlog scope, and sometimes shaping and estimation too. If it runs past four weeks, I’d want to know why.
Walking Skeleton
Section titled “Walking Skeleton”A walking skeleton is a thin, end-to-end implementation of one trivial feature, which proves the architecture works before any real functionality is built on it. The term comes from Alistair Cockburn; the version I reach for is in chapter 4 of Steve Freeman and Nat Pryce’s Growing Object-Oriented Software, Guided by Tests. Mine should:
- Touch every layer, end to end: UI, API, database, and messaging if the design uses it.
- Be deployed through the pipeline to a real, non-local environment, so deployment is proven from day one.
- Have tests in place, including an end-to-end test running in CI.
- Have observability wired in, because it’s what unlocks the other quality attributes later on.
The risk is the one described in Early Solutions Become De Facto Solutions: the skeleton quietly becomes the architecture. I guard against that in two ways. I keep it deliberately thin, with only the minimum needed to prove the path and no domain logic to entrench. And I treat its decisions as a hypothesis, reviewing them explicitly after the first few sprints and recording which ones are still provisional.
Code & Design Reviews
Section titled “Code & Design Reviews”- Reviews should primarily ask: is this correct and will it be maintainable? Style is a secondary concern and should be automated.
- Separate design review from implementation review. Reviewing an architecture decision in a PR is too late.
- Leave the code better than you found it, but don’t block a PR on unrelated refactoring. Raise a ticket instead.
Stakeholder Communication
Section titled “Stakeholder Communication”- Lead with outcomes and risk, not technology. Business stakeholders care about what can go wrong and when things will be ready.
- Write things down. Verbal alignment that isn’t captured will be reinterpreted.
Onboarding Engineers
Section titled “Onboarding Engineers”- First PR within the first week: keep it small and low-risk.
- Mentor, then review. Guide them through their first non-trivial task, then review it together rather than pairing on it.
Personal Preferences
Section titled “Personal Preferences”These are my current preferences. They are opinionated, context-dependent, and will change as I learn. The point is to make my defaults explicit so I can reason about when to deviate from them.
Architecture Style
Section titled “Architecture Style”- Start with a modular monolith. Extract services when a specific team or scaling boundary demands it, not up front.
- Event-driven where coupling is the problem, not as a default. Async is harder to debug and reason about.
- API-first. Define the contract before writing implementation.
Testing
Section titled “Testing”- Test behaviour, not implementation. Tests that break when you refactor but not when the behaviour changes are noise.
- Developer tests over unit tests for I/O-bound code. Mocking the database hides the interesting failure modes.
- A failing test in CI is a blocker, not a known flaky test to skip.
