What protects you, precisely.
Some promises here are properties of the system. The rest are in writing. We tell you which is which.
Your partner only ever sees what you both said yes to.
When both partners have finished, the comparison runs on our servers, in a privileged context neither browser can reach. What returns to your client — and to your partner's — is the intersection only: the things you both said yes or maybe to. Your unmatched answers are not styled and hidden, not blurred, not paywalled. They are simply never sent to your partner.
// When both partners have submitted, on the server:
async function computeReveal(partnershipId) {
// privileged server context — no client can reach into this
const [a, b] = await loadBothResponseSets(partnershipId);
const overlap = sharedQuestions
.filter(q => isMutual(a[q.id], b[q.id]));
// mutual = yes·yes, yes·maybe, maybe·maybe
return overlap; // the only thing either client is ever sent
}Encrypted in transit, encrypted at rest, scoped to your rows.
Your answers travel over TLS 1.2 or higher and live in Supabase Postgres, encrypted at rest with AES-256 — platform-managed keys, rotated by people whose whole job that is. On top of the encryption, row-level security scopes every user-facing query to your own rows: your session cannot read your partner's answers, or anyone else's. What we do not have is client-side encryption, and we will not pretend otherwise — the protections here are the boring, load-bearing kind.
-- row-level security · every user-facing table
alter table quiz_responses enable row level security;
create policy "own rows only" on quiz_responses
for select using (auth.uid() = user_id);
-- in transit: TLS 1.2+ · at rest: AES-256 (platform-managed)
-- your session token cannot read your partner's rowsExport and deletion are one click, in Settings.
Neither requires emailing anyone. Export gives you an instant JSON download of everything we hold — profile, responses, matches, journal. Deletion is permanent and irreversible: it removes your auth user, cascades through every table that references you, and cancels your Stripe subscription as part of the same flow. Deleted data drops out of our daily backups as the 30-day retention window expires. There is no archive, and there is no “in case you change your mind” — if you change your mind, you sign up again.
// Settings → Export my data (instant JSON download)
GET /api/account/export
// → profile, responses, matches, journal
// Settings → Delete my account (permanent, immediate)
async function deleteAccount(userId) {
await cancelStripeSubscription(userId);
await auth.admin.deleteUser(userId); // cascades through every table
}
// Daily backups expire on a 30-day window. No archive.We will never train AI models on your answers.
This is not a soft commitment we might revisit during a strategy offsite. It is a written restriction in our data processing agreement — and we want to be precise about what kind of promise it is: contractual, not cryptographic. We could not quietly change our minds; the clause survives termination and cannot be amended without notice to every active customer and an opt-out window. Your answers are product data, never training data.
// excerpt from the BothWant Data Processing Agreement, §4.2
// available at /legal/dpa, executed by BothWant Editorial.
PROHIBITED USES. Processor shall NOT:
(a) use Customer Data to train, fine-tune, evaluate,
or otherwise improve any machine-learning model,
whether owned by Processor or by a third party;
(b) grant any license to Customer Data that would
permit such training by a sub-processor;
(c) retain or repurpose Customer Data beyond the
operational purposes described in §3.1.
// This clause survives termination. It cannot be amended
// without notice to all active customers and an opt-out window.We do not sell, share, or transfer your data to advertisers.
We have no advertiser SDKs in our codebase. No Meta pixel. No Google Ads tag. No TikTok pixel. No LinkedIn Insight tag. The only third-party scripts on bothwant.com are the ones we list publicly: Stripe (checkout), Resend (transactional email), and PostHog (product analytics with PII masking enabled). You can verify this. The build is open to inspection in the browser, and our sub-processors page lists every vendor we touch.
$ rg 'connect.facebook.net|googletagmanager|doubleclick|tiktok|linkedin\.com\/insight' .
# (no matches)
$ rg 'pixel|fbq|gtag|ttq|_linkedin_partner_id' --type js --type ts
# (no matches)
$ cat package.json | jq '.dependencies | keys[]' | grep -i 'pixel\|analytics\|tracking\|ad'
"posthog-js" # the only match — and PII masking is enforced in posthog.config.tsThe architecture, step by step.
You answer alone, in your own session. Everything travels to our servers over TLS 1.2+, behind strict security headers (CSP, HSTS) and an age gate at the door.
Answers live in Supabase Postgres, encrypted at rest with AES-256. Row-level security means your session can read your rows and no one else's. Rate limiting sits in front of the API.
When both partners have answered, the server compares the two sets and computes the mutual overlap — yes-yes, yes-maybe, maybe-maybe. Neither client participates, and neither client can call into it.
Each partner's client receives only the intersection. Your unmatched answers — yours alone, the embarrassing ones — are never sent to your partner. They are not in the payload at all.
The threat model couples actually care about. The reveal runs server-side and returns only the mutual overlap — your unmatched answers are never in your partner's payload. There is nothing to find in dev tools, because nothing was sent.
Data is encrypted at rest (AES-256) and in transit (TLS 1.2+). Passwords exist only as salted hashes held by our auth provider. Card numbers never touch our servers — Stripe holds those. Row-level security and rate limiting narrow what any single stolen credential could reach.
There is no dashboard where any of us — engineer, support — can browse what couples have said yes to. Production access is restricted to operating the service, and the DPA above makes “we don't look” a contractual obligation, not a mood.
We are not making you safer than you already are.
A few honest limits. We do not replace a therapist's judgment, and we cannot recognize a pattern that requires one. We do not prevent harm in relationships where harm is already happening; we do not detect coercion through a quiz. If a partner pressures another into using BothWant, the architecture cannot tell.
We are a US software company subject to US legal process, and we will respond to lawful subpoenas the same way every other US software company does. What limits what we can be compelled to produce is not cryptography — it is minimalism. We collect little, we keep it only while you keep an account, and deletion is real, immediate, and ages out of our backups within thirty days.
If something on this page is meaningfully wrong, we want to know. There is a vulnerability disclosure path below.