What I build

Eleven years of infrastructure engineering across databases, platforms, web applications, and AI agentic systems. Currently at Stripe on the Database Engine team; previously VMware, Rippling, and Lavelle Networks.

Almost everything below started as a problem I hit at work and could not buy a good answer to, so I built one. It is grouped by the problem it solves rather than by language or repository.

I take on a small amount of consulting work in these areas.

01 / Multi-tenant data & identity

Systems that know whose data this is

A product that serves one customer per database is simple. One that serves ten thousand is a different system. Tenancy has two halves: a data plane that decides which shard holds a customer's rows, and a control plane that knows who the customer is, what they may do, and what they owe. Most teams build neither, so tenant state ends up scattered across an auth provider, a billing dashboard, and a spreadsheet.

Postgres wire protocolShardingCross-shard transactionsMulti-tenancyRBACOAuth 2.0JWTStripe billingGo

Tenant-aware Postgres proxy

Unreleased

A wire-protocol proxy that clients connect to as if it were Postgres. It reads tenant identity out of the query, routes to the shard that owns those rows, fans out and merges when the key is absent, and coordinates commit across shards with best-effort rollback. Wire adapters stay separate from the routing core, so other databases can plug in later.

System of record for organisations

Current

One service that owns the whole organisation lifecycle, covering orgs, their users, authorisation, and billing, so tenant state stops living in three vendor dashboards. Merchants configure policy centrally and enforce it inside their own backend.

OAuth integration broker

Configure an external provider once, then fetch a valid token for it over a plain REST call from any application, indefinitely. It removes per-project OAuth flows, refresh logic, and secret storage from every downstream service.

Standalone authorisation layer

Permissions extracted into a library so access rules stop being re-implemented, slightly differently, in every service that needs them.

Token and session auth service

Shared user management built because rewriting it per project stopped being defensible: session tokens, JWT, and OAuth first, with a path through directory protocols, MFA, and time-bounded access.

Multi-tenant SaaS foundation

A production-grade Go starting point that stitches the full stack together without a heavyweight framework: JWT auth, role-based access control, Stripe billing across plan tiers with webhook handling, account-isolated projects, migrations, and a generated client SDK.

Backend-agnostic persistence layer

Define a Go struct, call save or find, and the adapter maps it onto Postgres, MySQL, SQLite, MongoDB, or ClickHouse. It trades SQL expressiveness for reaching persistence fast.

Self-hostable form platform

An open-source alternative to the dominant form SaaS: Postgres, OAuth sign-in, and a Docker Compose stack that comes up from a single env file.

02 / Database & storage internals

The layer below the query

When a database becomes the bottleneck, the fix usually sits below the query layer, in the replication path, the snapshot mechanism, the lock granularity, or the cache in front of it. I have built these pieces from scratch rather than configured them, in Go and in Rust, because that is what it takes to reason about them under load.

RaftWALChange data captureCopy-on-write snapshotsRedis internalsSQLite internalsHash table designLock stripingGoRust

Logical replication on Raft

Consensus and log replication implemented from first principles, built to close the gap between understanding Raft and actually shipping it. A coordinator drives independently runnable managers for WAL generation, log replication, and leader election, exercised against a three-node cluster in the test suite.

Copy-on-write point-in-time snapshots

Snapshot semantics for an in-memory store with zero additional memory cost until data is mutated and minimal impact on read latency. A snapshot buffer layers over shard threads, with simultaneous snapshot instances and cross-shard restore, and no dependence on an OS-level fork.

Change data capture for live migration

Move a collection between clusters with negligible downtime: bulk-copy what exists, record the start timestamp, then tail the oplog from that point until lag closes. A self-contained path off a managed migration service and its lock-in.

Redis-compatible engine with live queries

Work on an in-memory database in Go that extends Redis commands with query subscriptions. Clients subscribe to a SQL-like query and receive a push when the result changes, rather than polling. Drop-in compatible with existing Redis tooling.

SQLite reimplementation in Rust

Work inside a from-scratch Rust rewrite of SQLite: storage engine territory, in a systems language with a different set of guarantees to Go.

Dragonfly-style dash tables

A Go implementation of the hash table design behind Dragonfly, written to understand its memory layout and probe behaviour rather than to read about them.

HTTP caching reverse proxy

Sits between the edge and the application server with a per-request in-memory response cache, invalidation APIs, and per-route skip rules for endpoints that must always reach the backend. It cuts backend load with no application-level change.

Concurrency and memory primitives

Striped locks across 1024 slots with FNV-32a key hashing, benchmarked against a single global mutex under contention. Plus a memory pool, and a ring buffer that flushes batches on message count, rollover, or time since the last flush.

Measurements, published

Benchmarks run and written up rather than assumed: protobuf against JSON across four compressors and eleven payload shapes, goroutine spawn cost against pre-allocated worker pools, interface dispatch against direct calls, and copy-by-value against pointer semantics.

03 / Platform & distributed runtimes

Getting workloads to run, on time, in order

Most teams do not need Kubernetes. They need a repeatable way to put a container on a machine, give it a database, and find out when it dies. Once the workloads run, something still has to schedule them, move events between them, and hold the pipeline together when a stage fails. That machinery is where delivery speed is actually won or lost.

DockerTerraformKuberneteskubebuilderKafkaPrometheus / GrafanaWebSocketsWebRTCAWSDigitalOceanGo

Self-hosted mini-PaaS

Current

Register SSH-reachable nodes, define an app, and deploy Docker containers to it, with no Kubernetes required. It provisions managed Postgres, Redis, Kafka, and Prometheus with Grafana, injects the connection details into linked services automatically, redeploys on a container-registry webhook, streams logs live, and runs a background health reconciliation loop.

Infrastructure as code across two clouds

Current

Terraform modules for AWS and DigitalOcean: VPCs and networking, instances, object storage, managed Kubernetes, and a Kafka node, with deployable manifests kept separate from the reusable modules.

Kubernetes operator

A custom resource and its controller on kubebuilder, covering both the standard reconciler pattern and external event sourcing, where events from outside the cluster enter the reconcile loop through a channel-based source.

Function executor and adaptive worker pool

A small function-as-a-service runtime, and a worker pool that sizes itself against the arriving work instead of spawning a goroutine per task.

Scheduler with a real data model

Current

Schedules hold triggers; triggers fire jobs built from templates with conditional logic and connector integrations. Absolute dates, relative offsets, and recurring intervals, expressed in a scheduling DSL that supports genuine pipelining. A structured replacement for a drawer full of crontabs.

Kafka pipeline DSL

Declare a source topic, a transformation, and a destination topic or external system, then chain the stages. Streaming pipeline logic in Go, for teams that want it without the JVM footprint of Kafka Streams or ksqlDB.

Event-driven workflow engine

Private

Composable stage definitions over Kafka with reliable delivery semantics, for pipelines where a dropped or duplicated event is a correctness problem rather than a metric.

Low-latency market data ingestion

A broker WebSocket client with binary protocol decoding behind a callback-handler interface, benchmarked for latency across 100k ticks. On top of it, an order management system covering placement, modification, and lifecycle tracking, and a tick-processing engine that runs rule-based strategies.

Global market aggregation

Current

Every major index, sector, and currency-adjusted return in one view, with valuation and macro overlays and capital-flow tracking, so the question of where the next unit of capital should go is answerable at a glance instead of out of a filing.

WebRTC selective forwarding unit

A minimal SFU handling multiple simultaneous producers and consumers, with the full signalling lifecycle: RTP capability negotiation, transport creation, and the producer and consumer handshakes. Conferencing infrastructure without a managed service.

API framework and load tooling

A Gin-based framework that exposes Go structs as CRUD endpoints with Rails-style lifecycle hooks around save and action, plus a config-driven parallel HTTP load driver that exercises an API without bespoke client code.

04 / Applied AI & agentic systems

Agents that survive contact with production

Agents are easy to demo and hard to run. The engineering sits in the plumbing around the model: routing events in from the systems people already use, keeping sessions coherent across turns, deciding what runs locally so the bill stays near zero, and making the output reproducible enough to trust twice.

LLM agent orchestrationTool and CLI integrationSession managementLocal inferenceWhisperRemotionffmpegGoPython

Agent orchestrator across messaging providers

Current

Bridges Telegram and Linear into a coding agent running locally. It fans incoming events from every configured provider into a single channel, invokes the agent per message, streams results back in chunks, and holds session IDs so multi-turn conversations stay coherent. Project bindings hot-reload from config every few seconds, with no restart.

Agent development environment

Current

A maintained library of agent skills and workflows: review, planning, release, and repository conventions encoded once, so an agent applies them consistently instead of being briefed from scratch each session.

Time-synced video generation pipeline

Any technical video in, animated overlays out. ffmpeg extracts the audio, a local Whisper model transcribes it with timestamps, a model detects technical scenes and writes the slides, Remotion renders them with spring animations and line-by-line code reveals, and ffmpeg composes the result. Keeping speech-to-text local holds API cost near zero.

Coaching application from gameplay analysis

Private

Analyses recorded play, tracks progress across sessions, and generates personalised drills and feedback rather than a single post-hoc score.

Local inference experiments

Running open models on local hardware to establish where a hosted API earns its latency and cost, and where it does not.

Also shipped

  • Interview preparation platform

    Merges the five best-known problem lists into roughly 326 unique problems, reorganised by 20 solution patterns instead of by data structure.

  • Mobile-first consumer app

    A lightweight product built around a clean, product-oriented architecture rather than a framework default.

  • Team and organisation management

    People, projects, and responsibilities held in one shared workspace instead of three disconnected tools.

  • Python dependency extractor

    Give it a file and an object name; it traces every transitive dependency and copies the closure into a mirrored source tree with the import hierarchy intact.

  • Go struct reflection utility

    Normalises an arbitrary struct into a name and an attribute map, with optional snake_case keys, for schema-less serialisation and structured logging.

  • REST layer over CSV files

    Post a set of paths and key-value filters, get matching rows back. Makes flat data queryable without standing up a database.

If one of these looks like the problem you are staring at, tell me about it.