DIKA
GET IN TOUCH

How I work

Last updated Jun 30, 2026

A short, honest description of my working style and defaults — useful if you're deciding whether I'd fit your team.

Scoping

I start by writing the smallest version of the change that a user would notice, then list what it deliberately excludes. That list is usually more valuable than the estimate: it makes the trade-offs reviewable before any code exists.

Write the problem statement

One paragraph, no solution language. If I can't write it, I don't understand the request yet.

Sketch the seams

Which modules change, which stay frozen, and what the rollback looks like.

Ship a thin slice

Get one real path working end to end behind a flag before widening it.

Write the doc page

Architecture and trade-offs, while the reasoning is still fresh.

Code review

  • I review for blast radius before style. What breaks if this is wrong at 3 a.m.?
  • I leave one-line comments with a location, a problem, and a suggested fix — no essays.
  • Nits get labeled as nits so nobody guesses whether they're blocking.

Testing

I aim for a small number of tests that would actually have caught real incidents, rather than coverage percentage. In practice:

// Property under test: total never drifts from the sum of its line items,
// regardless of discount ordering.
test("discount ordering does not change the total", () => {
  const cart = buildCart([item(1200), item(499)]);
  expect(applyDiscounts(cart, [percentOff(10), flatOff(200)]).total).toBe(
    applyDiscounts(cart, [flatOff(200), percentOff(10)]).total,
  );
});

Warning

I'm skeptical of tests that assert implementation details. They fail during refactors and pass during outages, which is exactly backwards.

Working with others

Written first, synchronous second. I'd rather post a short design note and collect comments asynchronously than hold a meeting to arrive at the same place. When something is ambiguous, I state the assumption I'm proceeding under instead of blocking.

Toolchain

Defaults, not dogma. Each of these is what I pick when there's no reason to pick something else.

Languages

LanguageWhere I use itWhy
TypeScriptWeb apps, APIs, toolingThe type system pays for itself at module boundaries
PythonData pipelines, scriptingEcosystem for anything data-shaped
SQLModeling, analysisThe most durable skill on this list
GoSmall services, CLIsSingle binary, predictable performance

Web

Next.js (App Router)

Server components keep data access on the server by default, which removes a whole category of over-fetching bugs.

Tailwind CSS

Styling stays next to markup and the design tokens live in one file. Fast to change, easy to review.

Zod

One schema validates the boundary and produces the type. No drift between the two.

Vitest + Playwright

Unit tests for logic, a handful of end-to-end tests for the paths that earn money.

Data and infrastructure

Postgres

First choice for almost everything, including queues and vectors until scale proves otherwise.

dbt

Version-controlled transformations with tests and lineage.

Terraform

Infrastructure as reviewable diffs rather than console clicks.

OpenTelemetry

One instrumentation layer, swappable backends.

Local setup

# pnpm everywhere, no exceptions — one lockfile format across projects
pnpm install
pnpm dev
 
# Postgres per project, in a container, seeded from a checked-in fixture
docker compose up -d db
pnpm db:seed

Note

I use pnpm rather than npm or yarn: the content-addressed store makes installs fast, and strict resolution catches accidental use of transitive dependencies before it becomes a production surprise.

Things I avoid by default

  • A separate vector database before Postgres and pgvector have actually become a bottleneck.
  • Microservices for a team small enough to fit around one table.
  • Custom CI runners before the hosted ones are demonstrably too slow.

Each is a reasonable choice under real pressure. None is a reasonable starting point, because they trade a problem you have for operational complexity you'll have forever.