← Selected work

Case study

Rivet

Multi-tenant issue tracking for teams that ship — built to practice production SaaS engineering in public: isolation, billing, jobs, observability, and written trade-offs.

Problem

Most portfolio trackers stop at CRUD. Rivet targets the questions hiring managers actually probe: how do you isolate tenants, bill safely, export without melting the request path, and observe failures when something breaks at 2am?

Role

Solo. NestJS API, React/Vite web, Prisma/Postgres, BullMQ, Stripe, MinIO locally / Backblaze B2 in prod (S3-compatible object storage), OpenTelemetry, Docker Compose, GitHub Actions CI, and ADRs for decisions that are hard to reverse.

Stack

NestJS · Prisma · PostgreSQL · Redis · BullMQ · Stripe · MinIO · Backblaze B2 · Vite · React · TanStack Query · OpenTelemetry · Prometheus / Grafana

Decisions

Trade-offs worth writing down

  • Tenant isolation without Postgres RLS (for now)

    One Nest service owns the database, so CLS + a Prisma extension enforce org scope on every query — including BullMQ jobs and Stripe webhooks. RLS stays a documented future backstop for compliance or a second DB consumer, not cargo-cult complexity today.

  • Field-level concurrency, not CRDTs

    Status and assignee use compare-and-swap; descriptions use a content hash; other fields are last-write-wins. Unrelated edits do not false-conflict. Illegal status transitions are rule violations (422), not concurrency conflicts (409).

  • Exports are always async

    POST returns 202 immediately. Workers stream rows, upload through an S3-compatible API (MinIO locally, Backblaze B2 in production), and hand back short-lived signed URLs. Quotas charge on insert; idempotency keys prevent double jobs; the API never streams CSV on the request thread.

  • Auth across origins

    Short-lived access JWT in the client, refresh token in an httpOnly cookie (SameSite=None; Secure in production). Org context is an x-org-id header validated per request — not baked into the access token — so switching orgs does not require re-login.

Proof

What you can verify

  • e2e coverage for cross-org isolation and RBAC — not only happy paths.
  • Architecture doc + ADRs for auth, tenancy, concurrency, and exports.
  • Docker Compose ships Prometheus, Tempo, and Grafana so you can see the same metrics and traces locally that Rivet sends to Grafana Cloud in production.
  • Explicit v1 boundaries: no RLS yet, no WebSocket board, no OAuth — deferred with reasons, not forgotten.

Longer write-ups on these decisions are queued in Writing. If you want a walkthrough, get in touch.