Building Eventra · Part 1 of 103 min read

The first week of Eventra: from a 45-line schema to a multi-tenant platform

  • buildinpublic
  • backend
  • prisma
  • saas
WEEK ONEIngestFeb 10AuthFeb 13BillingFeb 15TenancyFeb 1816 commits in 9 days

I have been working as a developer for about eight years. In that time I had never built a complete product alone, from the first line to a running service. Eventra is that project: a personal challenge to design, build and ship every part myself.

This is the first post in a series about how it was built. I'll stick to what happened and why.

Day one: backend first

The first commit is from February 10: "Initial commit: ingest API with Prisma and aggregation".

I started with the backend because everything else depends on it. A dashboard with no data behind it shows nothing, and an SDK with nowhere to send events has no purpose. The stack: NestJS, Postgres and Prisma.

The Prisma schema in that commit is 45 lines and has three models. That is the entire product at that point: an app sends "this feature was used", and Eventra counts it.

The README in the same commit is 557 lines long. I was working alone, and writing the design down was how I kept it structured so I could pick it up the next morning without losing the thread.

The product at the start

Eventra began as a feature tracker: a backend, a dashboard, and a list of features that users recorded by hand. The dashboard showed how much each one was used.

That model changed within weeks. A list maintained by hand goes stale, so the list of features had to come from the code. That is the subject of the next post.

What the week looked like

Between February 10 and 18 there are 16 commits:

  • Feb 10-11: single app turned into a monorepo, dashboard and SDK added.
  • Feb 12: "deliver end-to-end feature tracking platform (ingest, aggregate, dashboard)". An event could travel the whole way.
  • Feb 13-14: auth, authorization, project isolation, sessions, workspaces, hashed API keys.
  • Feb 15-16: public signup, onboarding, usage tracking, and billing with usage alerts.
  • Feb 17: reliable billing, safe handling of repeated events, plan limits.
  • Feb 18: project-scoped access control, invites, strict multi-tenant enforcement, and a commit called "audit".

Each step followed from the previous one. A product with users needs accounts. Accounts need workspaces so people can share. Workspaces need isolation so one can never read another's data. Plans with limits need enforcement (the plans themselves are covered in how Eventra is priced). That chain is how a feature counter turned into a billing state machine in seven days.

What took the most work

The main work of the week was connecting all the pieces: ingest, rollup, auth, billing and the UI had to fit together as one system, and I was deciding that fit for the first time.

Architecture. I kept reworking the layout until the structure held up. The monorepo split on day one and the "production architecture and multi-tenant model" documentation on February 15 are what that looks like in git: I refined the structure while building on top of it.

Prisma migrations. The schema changed daily in the first week, and the migration history had to keep up. Locally that produced migration conflicts that I resolved one by one. The result is visible in git: the schema moved into a shared database package, with a fresh init migration on February 17 and twelve migration files by then. Everything ran locally, so nothing was at stake except time.

The audit

The last commit of the week is called "audit". It marks the point where I stopped adding features and started checking what I had built. Working alone, nobody else reads your code, so you have to schedule that review yourself. I'll cover what the later audits found in a separate post.