Not a list of technologies. The reasoning behind each one, and what it costs us when we're wrong.
Guarantees first. Features inside them.
Most systems fail because nobody chose what they must never do. Ordering, consistency, durability, privacy: these get assumed rather than decided, and assumptions do not survive load. So we settle them first.
Only then do we design the product — inside the constraints those guarantees create. It looks slower on day one. It is faster over the life of the system, because the rewrite that usually comes never does.
Eight things we do, and how we do them.
Architecture
Decide the guarantees before the diagram.
We start from the invariants a system must never violate: ordering, consistency, durability. The structure is derived from those. Boundaries follow data ownership, not org charts, so a service can be understood without reading the ones around it.
Backend
Go services that stay simple under load.
Statically-compiled Go behind gRPC, with Postgres as the system of record and Redis where latency demands it. Handlers stay thin, domain logic stays testable, and anything slow moves to a queue rather than a bigger machine.
Frontend
Server-first React that ships less JavaScript.
Next.js App Router with React Server Components by default. Client components are the exception, reached for only where interaction demands them, which keeps the hydration cost proportional to what's actually interactive.
Mobile
One Flutter codebase, native where it counts.
Flutter for iOS and Android against the same API contract the web uses. We drop to platform channels only for the things that have to be native: biometrics, secure storage, background sync.
Cloud & infrastructure
Every environment is a Terraform plan.
GCP, described entirely in Terraform. There is no console-clicked resource anywhere in production, which means an environment can be rebuilt from an empty project and a git checkout.
DevOps
Deploys are boring on purpose.
Trunk-based development, containers built once and promoted through environments, progressive rollout with automatic rollback on SLO burn. The engineer who wrote it is the one who ships it.
AI
Models narrate. Code computes.
Retrieval over your own data, deterministic aggregation before inference, and evaluation suites that gate every prompt change. If a model states a number, that number was calculated in code first. The model is never the source of truth.
Data
Schema is a contract, migrations are code.
Normalised Postgres with explicit, reversible migrations that run in CI before they run anywhere else. Analytics reads from replicas, so a slow dashboard query can never take the product down with it.
How an engagement runs.
Discover
Understand the domain and, more importantly, the failure you're trying to avoid.
Design the guarantee
Settle ordering, consistency, durability, and privacy before a line of feature code.
Build inside it
Ship the smallest thing that's true, constrained by the invariants we chose.
Harden
Evaluation suites, load, and deliberate failure injection until it holds.
Operate & hand over
SLOs, runbooks, and on-call — so the team that owns it can run it.
What we won't compromise on.
The guarantee comes first
We decide what a system must never do before deciding what it should. The rest is derived from that.
Boring infrastructure wins
We choose tools for operational calm, not the changelog. Reproducible, observable, and hard to surprise.
Evals gate the merge
A prompt or model change ships only when the evaluation suite says it's at least as good as what's live.
Own what you ship
The engineer who designs a system builds it, ships it, and carries the pager for it. No walls to throw things over.
Write the decision down
What we chose, what we rejected, and what would change our minds. Six months later it's the only thing that still works.
Design for the tired engineer
A system that needs a hero at 3am is broken. We build for the version of ourselves that's out of sleep and patience.
The stack we bet on.
Every tool here is one we run in production and can support at 3am. Chosen for operational boredom, not for the changelog.
- Go · Services
- TypeScript · Web
- Next.js · Frontend
- Flutter · Mobile
- Python · AI / data
- PostgreSQL · System of record
- Redis · Cache / presence
- Kubernetes · Orchestration
- Docker · Packaging
- Terraform · Infrastructure
- GCP · Cloud
- gRPC · Transport
Four rules we don't bend.
Every team says they care about quality. These are the specific calls we make when caring about it costs something.
Correctness is a feature.
A system that is fast and wrong is just wrong sooner. We pick the guarantee first (ordering, consistency, durability) and then make it fast inside that constraint.
Boring infrastructure, ambitious products.
Postgres, Go, containers, Terraform. We spend our novelty budget on the product surface, not on the parts that page someone at 3am.
AI that reasons over facts, not vibes.
Models narrate; they don't compute. Every number an AI feature reports is derived deterministically before the model ever sees it, and every claim traces back to its source.
Own the thing you ship.
The engineer who builds a service runs it. That closes the loop between the design decision and the pager, which is the only thing that reliably produces good design decisions.
Have a system that needs to hold up?
Bring us the hard part. We'd rather work on the thing that scares you than the thing that's easy.