How I approach engineering

The craft behind the shipped code

Less a process diagram, more a working contract with the code. ADRs before architecture, schemas before endpoints, tests before merges, observability before features, small commits and frequent deploys. None of this is original. Doing it consistently is the difference.

Small commits
Frequent deploys
ADR-led
Decisions written down
Observability first
Before the first feature

Eight practices that hold the work together

None of these is glamorous on its own. Lived together, they are why the code I ship at noon is still running unattended at midnight.

01

Frame the problem in writing

A one-pager before a single line

Before any code, the problem gets a one-pager. What is true today, what changes, what the failure modes are, what is explicitly out of scope. The doc lives in the repository under docs/adr so the next engineer can read the decision and understand why, not just what.

docs/adr/0001-problem-statement.md
Explicit non-goals
A linked failure-mode list
Reviewable in a pull request
02

Design before build

ADRs, diagrams, trade-off notes

Architecture decision records for the load-bearing calls. Mermaid diagrams in the repository so the picture renders on GitHub. Trade-off notes that name the rejected options. By the time the first commit lands the shape is already legible.

ADRs for the load-bearing decisions
Mermaid diagrams in /docs
Rejected options written down
Stack selection justified, not assumed
03

Schema and contracts first

Data model leads, code follows

The Postgres schema goes in with row-level security from migration one, denied by default, explicit policies per role. API contracts are typed end to end, validated at the edge with zod or pydantic. Drift between the schema and the application is caught at build time, not in production.

Versioned SQL migrations
RLS denied by default
Typed contracts at the edge
Generated types checked into the repo
04

Small commits, trunk-based

Many tiny merges, not few large ones

Short-lived branches off main. Conventional commit messages so the changelog writes itself. Pull requests sized to be read in one sitting. The reviewer is also the deployer, so the loop stays tight.

Conventional commits
Pull requests under 400 lines
main is always shippable
Squash on merge, history stays clean
05

Tests where they earn their keep

Critical paths covered, not vanity coverage

Unit tests for pure functions and tricky boundary cases. Integration tests for the database layer and the auth boundary. A small end-to-end suite for the headline flows. Tests are run in CI on every pull request and pin the behaviour, not the implementation.

Unit tests for boundary cases
Integration tests for RLS
Headline end-to-end flows
CI gates the merge button
06

Observability before features

You can see the system before you ship it

Structured logs with request IDs. Error tracking wired up on day one. A health endpoint that means something. Dashboards for the four golden signals. Before the first user-visible feature ships, the team can already see what the system is doing.

Structured JSON logs
Sentry or equivalent wired
/api/health returns the build
Latency and error dashboards
07

Deploy small, deploy often

Many cheap releases beat one heroic launch

Every merge to main triggers a deploy. Preview environments on every pull request. Feature flags for the things that need a controlled rollout. Rollback is a single click because the build is immutable and the database migration is reversible.

CI deploys main on green
Preview env per pull request
Feature flags for risky rollouts
Reversible migrations only
08

On-call discipline

Alerts that mean something, runbooks that work

Alerts only on signals that need a human, never on the noise above. Each alert points at a runbook in the repository with the exact mitigation. Post-incident reviews live in /docs so the next surprise is a different one.

Pageable alerts, scoped tight
docs/runbooks/<alert>.md
Post-incident write-ups
No silent failures
Cadence

The rhythm the code lives at

Engineering discipline is mostly a habit of small loops. Six loops, each one short enough to stay honest about.

Daily

The smallest loop

  • Pull main, rebase the branch.
  • Write tests for the change before the change.
  • Push small, focused commits with conventional messages.

Per pull request

The trunk-based gate

  • CI runs lint, type-check, tests, build.
  • A preview environment renders the change.
  • Self-review pass before request, then merge to main.

Weekly

Pause to look at the system

  • Read the error tracker, triage open noise.
  • Skim latency dashboards for slow regressions.
  • Sweep dependabot, rotate any flagged secrets.

Per release

Boring deploys, by design

  • Migrations applied forward, reversible by default.
  • Feature flag the risky surface.
  • Tag the build, link the changelog, leave the runbook updated.

Monthly

Whole-system check

  • Capacity and cost review, written up in /docs.
  • Backup restore test on a clean environment.
  • Audit-log spot-check on the high-risk tables.

Quarterly

Architecture audit

  • Re-read every ADR against the current code.
  • Update diagrams that have drifted from reality.
  • Retire dead code paths and stale feature flags.
Engineering invariants

Things that hold across every project

Eight invariants the code respects regardless of scope. Each one is cheap on day one and expensive to retrofit on day a thousand.

RLS denied by default

Every table starts with row-level security on and no policies. Access is added explicitly per role. The default is locked, the exceptions are written down.

Structured logs, request IDs

No printf debugging in production. JSON logs with a request ID that follows the call through every layer, including the database, so an incident is a grep away from a story.

main is always shippable

Short-lived branches, CI gates the merge button, no half-finished features sat on main behind a comment. Either it ships or it sits behind a flag.

No secrets in the repo

Secrets live in the platform vault, never in the working tree. The pre-commit hook blocks any obvious leak. Rotation paths are documented in the same place.

ADRs over tribal knowledge

The decisions that shape the system live in /docs/adr in plain Markdown. Whoever inherits the code can trace why, not just what. Tribal knowledge is a bug.

Runbooks for every alert

If something pages a human, there is a runbook in the repository with the mitigation. Alerts without runbooks get either a runbook or a deletion.

Boring stack, sharp tools

Postgres, TypeScript, Python, Go, Rust where it earns its place. No technology picked to look impressive. The next engineer can read it without a glossary.

Tests on the boundary cases

Not vanity coverage. Tests sit where the system is most likely to lie: input validation, RLS policies, retry semantics, time zones, money. The hard parts get pinned.

Why this matters to a hiring team

None of the above is a marketing line. Every invariant is observable in the public repositories: the migrations show the RLS, the workflows show the CI, the runbooks live in /docs. A hiring team can audit the discipline before the first conversation. Sarma is taking PAYE full-time roles only until 14 February 2030.