A queryable roster of who belongs where

A database mirror of company membership so notification rosters and team lists can be queried directly instead of scanning the identity provider on every request.

What it is

A table holding one row per person per account, with their role, status, crew and contact details. The identity provider remains the authority during the dual-write period; this is the queryable copy that removes provider scans from hot paths. It self-heals — every app load writes the caller's row — and readers treat an empty result for an account as 'not seeded yet' and fall back to the provider.

Also called: org members table · membership record · who is in this account

See it
A queryable roster of who belongs where
CustomerBuildingAmountStatus
Sutter KlineBarndominium$17,160Sent
Marlin Hoover30×40 Garage$1,390Approved
Sutter KlineBarndominium$17,730Draft
Ivy Brubaker40×64 Shop$15,070Approved
Ivy BrubakerHobby Shop$18,110Draft
The Team page roster with role chips and a 'no login yet' hint on people who exist only as crew records. Data via src/lib/membership.ts and src/lib/orgRoster.ts. Sample data — no customer information appears here.
How it works
  1. 1syncOrgMember() upserts on (account, user), sending only the fields the caller actually has.
  2. 2Writers are the per-load bootstrap endpoint, the signup webhook for owners, the approval endpoint, and a backfill script.
  3. 3membersOf() returns approved members of an account — the notification-roster read.
  4. 4membershipsOf() returns every account a person belongs to.
  5. 5A crew id is validated against the account before it is stored; a crew the account doesn't own is stored as no crew.
  6. 6Platform staff visiting a customer's account are deliberately NOT written into this table.
Why we built it

Two guards carry the interesting history. The crew guard, dated 08-25: the biggest caller reads the crew id from per-user identity metadata, 'which is per-USER, not per-org — so someone on a crew at one builder had that crew's id stamped onto his membership row at every OTHER builder he opened', which took a person off their real crew's roster. The fix is placed at the choke point on purpose: 'The caller can't be trusted to know, and shouldn't have to: check it here, once, for everyone.' The staff exclusion is equally deliberate: that table 'is the tenant's own roster… a support call would otherwise silently enrol a Leads 2 Build employee as an employee of the builder.'

The problem
  • Notification rosters required scanning the identity provider on every send.
  • A crew id from one company was being stamped onto memberships at every other company.
  • Vendor staff visiting an account were being counted as that company's employees.
Sound familiar?
What you get
Team lists and notification rosters resolve from one query.
A person's crew is only ever a crew their employer owns.
Your team list contains your people and nobody else's.

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →