Blog · 11 min read

Anchored identity in multi-tenant SaaS: when one person wears many roles

A customer who becomes an employee, or an owner who becomes a customer, is still the same person — the system needs to know that.
By · published on

Case study · platform engineering. Meta Dados methodology (Genba · Kanso · Omotenashi).

Summary. In multi-tenant SaaS within the services domain, the same human being shows up as customer, employee, and owner — sometimes across several establishments. We model this problem as an anchored identity graph: a global entity (the person, anchored by the CPF) toward which denormalized per-tenant links converge. A controlled experiment, run against the production database within a transaction with ROLLBACK, shows that identity unifies correctly by CPF, but that the denormalized data silently diverges across tables and that a class of entry points that creates an "inline" login with a null CPF splits one human into two identities. We describe two verified interventions and derive reusable principles.

1. Introduction

Scheduling platforms treat three entities as first-class citizens — customer, employee, and establishment — each with its natural key: the customer is recognized by phone number; the employee requires a CPF; the establishment identifies itself by CNPJ + email (or CPF, for the sole proprietor). The problem arises because these three are not disjoint: a customer can be hired and become an employee; a customer can open their own business; an owner can book as a customer at another salon. The system needs information to travel between the tables and stay consistent, with no vital data diverging across different records.

We treat the Marcaê platform as a case study, but the model and the findings are general: they hold for any SaaS where an individual takes on heterogeneous roles over time and across tenants.

2. The model: anchored identity

The core idea is to separate identity from role. The person is a global entity — tenant-less, anchored by a strong key (the normalized CPF). Each link (customer, employee, user) carries a denormalized copy of the vital fields and a person_id foreign key pointing to the person. A database trigger (vincular_pessoa_por_cpf) performs the find-or-create: when a link is written with a valid CPF, it associates (or creates) the person for that CPF and sets the person_id. Without a valid CPF, the identity is local to the tenant.

ESTAB. AESTAB. BCustomerEmployeeOwnerCustomerPERSONunique CPF · anchorname · email · phoneno CPF → identity local to tenant
Anchored identity graph: links from multiple tenants converge (fan-in) onto a single person via person_id. Without a CPF, the link stays isolated within the tenant.

3. Invariants and divergence metric

The model must guarantee two invariants. The first is identity unification (I1): two links with the same valid CPF point to the same person. The second is role completeness (I2): the person knows all the roles (tenant + role) derived from their links.

To measure the consistency of the vital data (name, email, phone), we define a divergence rate δ: the fraction of people for whom some vital field has more than one non-empty value between the anchor and its links. δ = 0 is the target — the person is the single source of truth.

4. The split-identity defect

A class of entry points creates the login account "inline" (together with the customer) using an anchoring that ignores the CPF — in practice, it always creates a new person. If a human passes through an entry point that anchors and through one that does not, they end up represented by two people — violating I1. The split rate σ grows in proportion to the use of the non-anchoring entry points. It is the highest-severity defect, because once identity is split, it can only be reconciled through a manual/SQL operation.

5. Methodology and results

We adopted Genba — going to the shop floor: instead of reasoning about the intended model, we exercised the real model. Two techniques: (1) an exhaustive reading of the 15 entry points where a customer/employee/user/owner is born or transformed, recording what each one writes and whether it anchors on the CPF; (2) transactional simulation — we instantiated identity journeys directly in the production database, inside BEGIN … ROLLBACK: the anchoring trigger actually fires, but nothing persists.

The results confirmed the model and flagged where it fails:

6. Interventions

Deduplication as an equivalence relation. The old rule collapsed two records by phone number alone; the new one requires normalized phone AND name. This way, two distinct humans who share a phone number (the mother who books from her own cell phone for her child) are no longer merged by mistake.

Merge as a field-by-field fold. When two records really are the same person, the merge stops being "pick one and discard the other" and becomes a per-field resolution: a diff table presents each divergent field side by side, and the operator chooses the value that stays on the survivor. Order matters — reattach the references and archive the removed records before applying the choice — otherwise the partial unique index collides. A merge that loses data is a regression; a field-by-field merge preserves the best of each record.

7. Discussion and principles

The case illustrates a recurring trade-off: denormalizing vital fields onto the links makes each screen fast and self-contained, at the cost of consistency; keeping the person as the single source of truth eliminates divergence, at the cost of read-time coupling. Reusable principles for any multi-tenant platform with shared identity:

8. Conclusion

Marcaê's identity unifies correctly when a CPF is present — the anchor works and is robust to role transitions. The class of entry points that split identity was closed off by a database trigger (reconciliation ensures the account follows the person of the CPF, the merge stopped generating orphan logins, and the anchor now learns the vital data it was missing). All that remains is the full single-source-of-truth — a design decision, not a defect. The gain is not only technical: it is the guarantee that a customer who becomes an employee, or an owner who becomes a customer, remains the same person throughout the entire system.

Systems we connect here

Frequently asked questions

Why not use the phone number alone to identify the person?

Because a phone number is not a strong key for a person: two distinct humans share a number (the mother who books from her own cell phone for her child), and a person changes numbers. Anchoring by CPF (a strong key, unique per individual) and using phone+name only as a deduplication relation avoids merging different humans by mistake.

Does this apply only to scheduling or to any SaaS?

The model is general. It holds for any multi-tenant SaaS where a single individual takes on heterogeneous roles over time and across tenants — marketplaces, healthcare platforms, education, property management. The principle "one anchor, one key; a role is a state, not an identity" carries across domains; what changes is the strong key and the set of vital fields.

Start at no cost

Does your platform have the same human across divergent records? Free diagnosis in 48h.

We map your current systems, point out the biggest bottlenecks and deliver a plan prioritized by risk × effort. You leave with clarity — whether you hire Meta Dados or not.

Get my diagnostic → Chat on WhatsApp No commitment, no credit card.
We reply within 2 business hours.
←  Voltar para Blog