I'm building Miraviso, a SaaS for hair salons. Most of its data is boring: appointments, product preferences, visit history. But one part is not boring at all: client notes can contain allergies and scalp conditions. That's health-adjacent data about people who never signed up for my service — they're my customers' customers.
The standard approach is encryption at rest plus TLS and a privacy policy. I decided that wasn't enough for this specific field, and the reason is threat-model honesty: encryption at rest protects against someone stealing the disk. It does nothing against the more realistic risks — a compromised application server, a leaky admin panel, a subpoena, or me making a bad query. In all those scenarios the application can decrypt everything, so the attacker (or the mistake) can too.
The envelope design
So for sensitive notes, Miraviso does something different: the encryption key is derived on the salon's device, and it never reaches the server. The client encrypts the note locally and ships an opaque blob — a sealed envelope. The server stores envelopes it cannot open. Not "won't open": cannot.
This is not full end-to-end encryption of the whole product, and I want to be precise about that. Appointments, scheduling, billing — all of that is processed server-side like any normal SaaS, because that's what makes the product work. The envelope treatment applies specifically to the fields where the server has no legitimate need to see plaintext, ever. The server's job for those fields is storage and sync, nothing more.
What it costs you
This design has real, permanent costs, and anyone considering it should stare at them before committing.
No server-side search. I cannot offer "find all clients with allergy X" as a server feature, because the server doesn't know what's in the envelopes. Any filtering over sensitive notes has to happen client-side, after decryption on the device. For a salon's client base that's fine; at a different scale it might not be.
Key management becomes a product problem, not just a security one. If the key is derived on the device, you have to answer: what happens when the salon changes tablets? Device loss and key recovery flows have to be designed as first-class UX, not as an afterthought — get this wrong and "the server can't read it" becomes "nobody can read it."
No server-side quick fixes. Support can't peek into a note to help a confused user. Migrations that touch encrypted fields need client participation. You're giving up operational shortcuts on purpose.
Why it's worth it for this field
Three reasons. First, breach impact: if my database leaks, the most damaging data in it is unreadable. The worst headline gets structurally smaller. Second, GDPR posture: for special-category-adjacent data, being able to say "we architecturally cannot access this" is a much stronger position than "we have policies." Third — and this is the one I underestimated — it's a sales argument. A salon owner understands "even we can't read your clients' health notes" immediately. It's one of the few security properties you can explain to a non-technical buyer in one sentence.
The general pattern
The takeaway isn't "encrypt everything client-side" — that kills most of what makes a SaaS useful. The takeaway is to segment your data model by who actually needs plaintext. Most fields: the server needs them, process normally, protect conventionally. A small set of fields: the server never needs them, so make it unable to read them, and accept the feature cost on exactly those fields.
In Miraviso the same segmentation shows up elsewhere: the AI color try-on runs fully on-device, while the haircut preview runs on EU servers with consent and is never written to disk. Different data, different treatment, each declared for what it is. You can read more about what I build on the home page.
If you're building a vertical SaaS that touches sensitive data — health, legal, finance — this per-field honesty is, in my experience, both the right engineering call and an underrated competitive one.