Lior Adan

Full-stack engineer & technical lead

Full-stack since 2019, based in Tel Aviv. I take a feature from the data model to the screen and ship it.

Stack
TypeScript, React / Next.js, Node.js, PostgreSQL, Cloudflare
Back to the whole tower

Building the model…

Floor 3 of 5 of the tower

Harbor CRM

Full-stack engineer · demo system

The interesting part of a multi-tenant app is what happens when someone forgets a filter.

The problem

Multi-tenant tools usually leak in one way: a query that forgot to ask “whose data is this?”. It works in every test until the day two clients share a screen.

The rules I set

  • Every row carries a tenant, and the database knows it.
  • The tenant comes from the session, never from the request body.
  • A boundary that lives in only one layer isn’t a boundary.

What I built

A tenant-aware CRM. Next.js and React on top, a typed tRPC API in the middle, PostgreSQL through Drizzle underneath. Row-level rules in the database, role-aware screens, and dashboards that read only through the tenant’s own scope.

How it’s layered

  1. UI Next.js and React screens that change with the user’s role.
  2. Typed API tRPC contracts the screens are checked against.
  3. Data PostgreSQL with row-level rules, defined through Drizzle.

Decisions

  • Tenant separation is a boundary in the application and again in the database.
  • Tests deliberately try to read another tenant’s rows and are expected to fail.
  • Screens stay in step with the API types, so a renamed field breaks the build, not a customer.

Where it stands

A demo system with generated sample data. It exists to show the layering and the two locks on every door.

TypeScript · Next.js · React · tRPC · PostgreSQL · Drizzle

Back to the whole tower

gebaut von Wild Digital Moments