Skip to content
ZERONE
Back to insights
Architecture Patterns2026-06-05 · 4 min readFrom Case 06

Anonymity as an architectural invariant: why "we won't contact you" isn't enough

Promises like "you will never be contacted unsolicited" aren't enforceable on B2B platforms — vendors route around them offline. What works is a technical invariant: contact data lives in a separated sphere, the server only releases it on a mutual match. A property of the code, not a TOS clause.

The classic B2B matching promise: "You will never be contacted unsolicited." Beautifully phrased. Not enforceable.

A platform can't prevent a vendor from doing offline research, pulling a company phone number out of the trade register and calling. The promise is a claim about the world — and the world is wider than any TOS contract.

What actually holds: architectural invariants

On PairSonal we reframed the promise. Instead of:

"We won't share your contact data."

it now reads:

"Your HR contact data is technically invisible to vendors on the platform — until you unlock a match yourself."

The difference isn't semantic. It's structural:

  • Contact data lives in a separated database sphere.
  • Listing endpoints return profiles whose payload simply does not contain email, phone, hr_contact.
  • The match endpoint joins onto the contact sphere server-side, and only after mutual unlock.
  • The frontend has no code path that could reconstruct fields that don't exist in the generated type.

The promise becomes a property of the code. Someone running "what happens when I load profiles?" finds the fields absent. Not "filtered", not "null" — not in the schema.

Why this is stronger

  1. Auditable. An auditor reads the OpenAPI schema and confirms: the contact fields don't exist in the anonymous sphere. That's a fact, not a TOS clause.
  2. Scales with headcount. A new teammate cannot accidentally build an endpoint that leaks the fields — they aren't in the data-model class they import.
  3. Survives auth bugs. A bug in the privilege layer can't surface hidden fields that don't exist in the response schema.

When this is overkill

Architectural invariants cost. You're effectively maintaining two data models, two repositories, two service classes, an explicit bridge between them. For a user profile with three attributes, that's overkill.

The point at which it pays off: when the promise is the product. If customers come to the platform because they trust the anonymity, anonymity can't live in a TOS clause. It has to live in the layer architecture — otherwise the product dies with the first leak.

The general rule

For any "we won't do X" promise we now ask ourselves:

Can we build it so that we technically cannot?

If yes: build it. If no: the promise is a claim, not a feature — and should be named as a claim, not sold as one.

A similar fire?

We've likely seen something close. Get in touch.

Talk to us