Skip to content
On a dark grid, one filled teal rectangle on the left fans out into five outlined boxes stacked in a column; thin lines from those pass through two bright dots on a vertical divide and lead into two larger outlined boxes on the right.

“Separation in the client is organisation, not security.”

Five kinds of user, one codebase

Service vendors, fleet carriers, owner operators, company drivers and a call centre — one product, five experiences, permissions resolved by type and role.

Get in touch
Technical leadership · US marketplace for truck services · team of 12 · 2022–2026 · same engagement
5
user types from one codebase
506
API routes across two separate sets
2
roles minimum, per user type
Summary

The platform served five kinds of user with genuinely different jobs. A vendor manages listings, invoices and renewals. A driver has recent searches, preferred vendors, call logs, trucks and repair tickets. A call centre operator works on behalf of others.

All of it from one codebase, with a separate internal CRM for the company's own team.

The problem

The tempting answer is five applications. It looks cleaner and it is faster for about six months. Then every shared change — a payment flow, a branding update, a security fix — has to be made five times, and it will be made four times, and nobody will notice which one was missed until a customer does.

The constraint

The opposite failure is just as common: one application with role conditions scattered through the interface. That version is impossible to audit. Asking “what can a driver actually do?” turns into reading the entire codebase looking for if statements.

What we did

  1. Separated by route, not by condition

    Each user type has its own set of routes under /dashboard/{user_type}/{page}. To know what a vendor can do you read the vendor's routes — not the whole application looking for if statements.

    One route set, one answer
  2. Resolved permissions as type plus role

    Every user type carries at least two roles — admin, owner, operator — and a permission resolves as the combination. A vendor's operator is a different subject from a fleet carrier's operator, even though both are called “operator”.

    Same name, different subject
  3. Checked on the backend as well

    Route-level separation in the client is organisation, not security. The API validates independently, because anything enforced only in the interface is enforced only against people who use the interface.

    Organisation is not security
  4. Split the API in two

    Public routes and admin routes are separate sets rather than one set with checks inside. The internal CRM is effectively its own product against its own surface.

    506 routes, two sets
FIVE USER TYPES, FIVE ROUTE SETS
Service vendor listings and invoices

Manages listings, invoices and renewals. Their operator sees listings but not invoices — the same role name, a different user type, a different permission.

All five share one codebase and differ by route set. That is why a shared change lands in one place, and the answer to “what can this user do” sits in one place too.

The result

  • Five user types and their roles from one codebase
  • 506 API routes across two separate route sets
  • Permissions auditable by reading one set of routes rather than the whole application

What we’d do differently

The permission model we built lived in the routing and in the API, but we never wrote it down anywhere a person could read as a whole. Onboarding a developer meant explaining it verbally, and verbal explanations of authorization models drift. A single generated table — user type against action — would have taken a day and answered the question permanently.

Related
Permissions as a graph on a HIPAA platformThe same question, a different shape of data.Four re-platformings, zero downtimeThe system these five kinds of user lived in.
All 18 case studies
  • React
  • Redux
  • Node.js
  • Express
  • MySQL

Five kinds of user, five applications?

Get in touch

Systems that can’t stop — from architecture to production.

© 2026 Micro Tech, Sarajevo