The shadow-mirror pattern, explained
How we keep internal deliberations and candidate-facing status in lockstep, without ever risking that a scorecard leaks into the candidate portal.
Most ATS platforms on the market today don't really have a candidate portal. They have a careers page, an application form, and then silence. Updates reach the candidate as a scattered trail of recruiter emails, DocuSign links, NDA attachments, scheduling back-and-forth, and the occasional "just checking in" reply. It's the 1990s communication stack stitched together with a modern logo on top.
We took a different bet with Nexus: candidates get a real-time portal that mirrors their journey. The moment you build that, though, you inherit a problem the rest of the industry has quietly avoided. Internal hiring data (scorecards, debrief notes, salary thinking, rejection reasons) lives in the same system as the candidate. One missed filter, one bad join, one curious URL, and a candidate sees something they were never meant to see.
The shadow-mirror pattern is how we make that category of mistake architecturally impossible, rather than something we hope a code reviewer catches.
The usual approach, and why it scares us
The default way to build a two-sided product is one database, with a visibility flag on sensitive fields. The candidate API is supposed to filter those rows out. In practice, this is a software-level if/else guarding some of the most sensitive data your company holds about a human being.
That model has two failure modes that should worry anyone in legal or security. First, every new query is a new chance to forget the filter. Second, in discovery or a breach investigation, the official answer to "could a candidate ever have seen this?" is "only if the code worked correctly every single time." That's not a defensible posture.
The scorecard isn't hidden. It isn't present in any table the candidate API can reach.
What shadow-mirror actually means
Instead of one shared database with permission flags, Nexus splits candidate-facing and internal data into separate tables with no shared query path. Internal deliberations live in shadow tables the candidate API has no route to. The candidate reads from a portal state, a sanitized projection that an internal write event explicitly mirrors into.
- A recruiter moves an application from "Onsite" to "Rejected: weak system design signal." That status, and the reasoning, lands in the internal table.
- In the same database transaction, a translation step writes a sanitized event to the candidate's portal state: "Process concluded." Plus the human follow-up the recruiter actually wants the candidate to see.
- The candidate portal queries portal state. It has no code path, no JOIN, no foreign key into the internal table. The scorecard is not hidden; it is not present in any table the candidate API can reach.
Same transaction is the important detail. The internal record and the candidate-facing view either both update or neither does. No drift, no stale portal showing yesterday's status while the team has already moved on.
Why recruiting and talent ops should care
The reason most teams default to email is not because email is good; it's because it's the only channel where they trust themselves not to leak. A debrief Slack thread, an internal scorecard, a comp range, none of that can be accidentally CC'd to the candidate, because the candidate was never on the thread.
Shadow-mirror gives you the same psychological safety inside the product. Coordinators can write candidly in internal notes, drop salary ranges into a debrief, mark a candidate as a strong no with reasons, without the cognitive overhead of "wait, can they see this?" The architecture answers that question for you. They cannot. Ever.
The candidate, meanwhile, stops living in the dark. They see where they are in the process, what's next, when to expect movement. The silence that quietly pushes strong candidates toward someone else's offer is exactly what the portal is built to close.
Why legal and infra should care
From a compliance and discovery standpoint, the line between internal deliberation and the candidate's record of truth matters enormously. With shadow-mirror, that line is a physical separation in the schema, not a convention in application code. The audit story becomes: here is the candidate's record, here is the internal deliberation, the candidate API can only reach the first. That's a sentence you can put in a SOC 2 narrative or a subpoena response without crossing your fingers.
From an infrastructure standpoint, the blast radius of a candidate-portal compromise is bounded by what lives in portal state. Even a full takeover of the candidate-facing API does not expose scorecards, internal notes, or comp data, because those bytes are not in the tables that API queries. That's a meaningfully different security posture than "we trust our row-level filters."
The trade-off, honestly
Shadow-mirror is more work than a single table with a visibility flag. There's a translation layer to maintain. Every new internal event that should reach the candidate needs an explicit mirror step. There is no "just expose the field." That friction is the feature. It forces an intentional decision, every time, about what the candidate sees.
We think that's the right trade for a product where the worst-case failure is a candidate seeing something a hiring team wrote about them in private. The rest of the industry skipped the portal entirely partly because this problem is hard. We'd rather solve it than avoid it.