Employer work. The architecture here is described at the level of the pattern — no internal service names, schema, or infrastructure detail. What's public is what I can explain without publishing someone else's system.
Shape of the platform
Ten backends — CRM, payments, notifications, recommendations, meeting intelligence, interviewing, internships — each starting out with its own idea of who a user was. Every new product meant reimplementing authentication, and every permission change meant finding all ten copies of it.
What ties three of them together isn't a call graph, it's a loop.
- Product apps: Six product frontends, plus an embeddable plugin that runs on somebody else's page. Not one of them carries its own idea of who a user is.
- Identity & SSO hub: The one service every product authenticates through. SSO, tokens with refresh sessions, OAuth, and a permission engine whose answers are cached with the tenant as part of the key — which turns cross-tenant leakage into a cache miss rather than something you hope a reviewer catches. It is also the platform's single point of failure. Every product's every request waits on it, which is the whole reason the cache exists.
- Product services: The domain backends behind those frontends. They never call each other anonymously — internal calls carry signed service tokens, so a compromised product cannot quietly act as the platform.
- Scoring: Turns a profile questionnaire into a single score on a fixed band. It is both the input the recommender ranks against and the output the loop rewrites once work is finished.
- Recommender: Finds the nearest comparable outcomes in a corpus of admitted profiles, uses that to decide what level is reachable, then generates activities at that level and gates them before any are stored.
- Learning Copilot: Takes the activity a learner picked and helps them do it — breaking it into sub-tasks, reading the actual work through connected tools, and remembering where they got stuck last time.
Two databases, on purpose
Identity, money and notification logs run on relational storage; product domains run on document storage. Not indecision — one extra ORM dialect, and the right tool on both sides of the line.
Identity and money must not drift. They want foreign keys, transactions, and a schema that refuses bad states outright.
Product data is schema-fluid, reshaped weekly. Running that against migrations is friction with no payoff.
The audit trail is where it earns its keep. When someone asks why an account has access it shouldn't, the answer has to be reconstructible — and that's a property of constrained storage, not of a document you can shape however you like at write time.
The webhook is the fast path, not the truth
A provider fires a webhook when money moves — and sometimes it doesn't arrive, arrives twice, or lands before the record it refers to exists.
Duplicates are free. Events are recorded idempotently, so a second delivery is a no-op.
Silence is caught. A scheduled reconciler sweeps for unresolved orders and settles them against the provider's own view.
So the webhook is an optimisation, not the truth. If every one vanished tomorrow the system would be slower and still correct — because a fact that matters has to be *checkable*, not merely announced.