Skip to content

Engineering Principles — How We Work

Not rules — beliefs. Rules are about what to do; principles are about how to think. When the rules don't cover a situation (and they often don't), these principles do.

Not rules — beliefs. Rules are about what to do; principles are about how to think. When the rules don’t cover a situation (and they often don’t), these principles do.

Choose the technology that is mature, widely used, and has a deep web of answers when you Google a problem at 2 AM. Postgres > exotic DBs. React > exotic frameworks. Drizzle > custom ORMs. We will rarely be the first team to hit a problem in a popular stack. We will routinely be the only team to hit a problem in a niche one.

We use boring tech for the load-bearing parts. We can be adventurous in places where the blast radius is small.

→ See ADR-0001 — Drizzle ORM for a worked example.

2. The reader matters more than the writer

Section titled “2. The reader matters more than the writer”

Code is written once and read fifty times. Every choice — naming, file structure, comments, abstractions — should optimize for the future engineer (often your future self) who has to figure out what’s going on with no context.

  • Verbose names beat clever shortcuts (organizationMembershipQueryParams beats oqp)
  • Inline a comment if removing it would surprise a future reader; otherwise don’t
  • Files have one reason to change (single responsibility, the SOLID one that actually matters)
  • 200 lines is a target, 400 is a hard stop — when a file grows, split

3. Mistakes are systems problems, not people problems

Section titled “3. Mistakes are systems problems, not people problems”

When something breaks in production, the question is why did the system allow it — not who screwed up. Every postmortem is blameless. We name the action (“a SQL filter excluded forge-cloud projects”), never the person.

This isn’t softness. It’s the only way to actually fix the underlying issue. If we blame people, we get cautious people who hide mistakes. If we blame systems, we get systems that catch mistakes early.

A rule without a guard rots. If you say “always do X” but nothing in CI enforces it, the next engineer (or AI) won’t. Every important rule must have an automated enforcement: ESLint, a scripts/check-*.sh, a pre-push hook, a CI step.

We treat “we should remember to do X” as a code smell — it means we have a rule we can’t enforce. Either find a way to enforce it or downgrade it to a non-rule.

→ Worked example: the Repository Pattern only stuck because ADR-0002 was paired with scripts/enforce-repository-pattern.sh as a CI hard gate.

5. Async by default; documents are the medium

Section titled “5. Async by default; documents are the medium”

Meetings are expensive. Real-time chat is medium-expensive. Documents are cheap.

  • A 1-page RFC reaches more people, more thoughtfully, than a 30-min meeting
  • Decisions live in ADRs, not Slack threads (Slack threads disappear)
  • If a discussion produces a decision, it goes in a durable doc — otherwise it didn’t happen
  • We’re remote-friendly because the docs work; the docs work because we invest in them

Done is better than perfect — for reversible work. A feature that ships and gets fixed in production teaches us more than a feature that lives forever in a PR.

For irreversible work (data migrations, breaking API changes, anything customer-visible at scale): measure twice, cut once. Use an ADR, get review, write a rollback plan.

The heuristic: how hard is this to undo? If easy, ship. If hard, slow down.

We use CMMD daily. We file bugs we find. We feel the pain that customers feel.

If the Sidekick is broken for us, it’s broken. If onboarding is confusing for new hires, it’s confusing for customers. Our team is our first cohort of users — and the loudest one we control. Listen.

We use AI tools (Claude, Cursor, Codex, our own Sidekick) heavily. Productivity is real. So is the risk.

  • The human who pushes the PR is responsible for every line in it
  • “The AI wrote it” is never an explanation for a bug
  • AI is great at boilerplate, mechanical refactors, exploring a codebase
  • AI is poor at: architectural judgment, prompt design for AI-facing features, knowing whether the rule should change or the code should change
  • If you don’t understand what the AI generated, you shouldn’t ship it

→ See AI Development Protocol

If a feature doesn’t have an analytics event, we have no way to know if it works for users. Every user-facing feature has a PostHog event via ANALYTICS_EVENTS constant. The Admin Adoption Pulse dashboard is where we look on Friday afternoons.

This is the Measurability Standard — non-negotiable. We don’t ship “I think users like it.” We ship “8% of weekly active users used it; here’s the conversion.”

Customers should feel us through the product, not through outages. Every deploy is small, frequent, reversible. Boring deploys are the precondition for exciting features.

  • Feature flags for anything risky (CLAUDE.md rule 16)
  • Backward-compatible migrations by default — see Runbook — Database Migration Deploy
  • Quick rollback path on every deploy (Neon branches, Railway rollback button)
  • Customer-impacting changes get a 24h notice when feasible

11. The 30-Second Rule applies to engineering too

Section titled “11. The 30-Second Rule applies to engineering too”

When you write a doc, a PR description, a postmortem — could a future engineer get oriented in 30 seconds?

  • Lead with the conclusion
  • Tables beat prose for comparisons
  • Code blocks for commands
  • Owner + date + status on everything

We’re a small team in a big space. The honest answer to most “should we do X” questions is “I don’t know yet — let’s find out.” Cultivate that. Strong opinions, loosely held. The opposite — pretending to know — produces brittle decisions and discouraged teammates.

When an ADR alternatives list is empty, the author didn’t try hard enough.

  • New hires read this on Day 1
  • ADRs cite which principle the decision rests on
  • Code review can say “rule violation” OR “principle violation” — both are valid
  • Once a quarter we revisit this page and ask: is any principle here actually unused? Is there a missing one?