Skip to main content
All technical notes

Security · November 2026

How we keep each organization’s data apart

2 min read · Shree Krupa engineering team

Our platform serves many organizations from one system. The most important thing it does is also the easiest to get wrong: making sure one organization can never reach another’s data.

The organization is part of every address

Every request for an organization’s data names that organization in its web address. Before any business code runs, a security check requires three things to agree: the address, a request header, and the organization named in the signed token. The person must also be an active member. If any of these disagree, the request stops there.

Controllers then check again, on purpose. If one layer is ever misconfigured, a single missed check shouldn’t mean a data leak.

Two tokens, not one

Signing in gives you a token that says who you are. To work in an organization, you exchange it for a second token that’s tied to that organization alone. A login token used on an organization’s address is refused, so you can’t accidentally act in an organization you haven’t entered.

Tokens carry no permissions

It’s common to put a person’s permissions inside their token. We don’t. Permissions are loaded on each request, so removing someone’s access takes effect straight away, not when their token expires.

Permissions only ever reach a person one way: person, then group, then role, then permission. There’s no shortcut for granting one permission to one person, which makes “who can do this?” a question you can answer.

Separate logins for each product’s data

Our separate products each have their own database, with their own login limited to what that product needs. A flaw in one product’s code can’t simply read another’s tables.

Where this has limits

  • Access applies to a whole app across an organization. There’s no limiting access by branch, project or client inside one organization, so we suggest separate organizations when data must be kept fully apart.
  • Loading permissions on each request costs a database lookup every time. We accept that in exchange for changes taking effect at once.
  • All of this protects against the application’s own mistakes and misuse. It doesn’t replace securing the servers it runs on.

Working on something similar?

Tell us what you’re trying to solve. We’ll reply within one business day and tell you honestly whether we can help.