Client-Side vs. Server-Side Encryption for Patient Data: What Healthcare Apps Actually Need
AES-256 client-side encryption vs. server-side encryption at rest — the real tradeoffs for healthcare and clinical software, explained from a live build.
"Is the data encrypted?" is one of the first questions asked about any healthcare platform, and it's usually answered with a yes that hides a more important question: encrypted where, and from whom?
We built Slotwise, a live appointment-scheduling SaaS for healthcare professionals, around client-side AES-256 encryption for clinical notes — meaning the note is encrypted in the browser before it ever reaches our servers. That's a deliberate, more expensive architectural choice than the more common alternative: encrypting data at rest once it lands on the server. Here's the actual difference, and when each one is the right call.
Server-side encryption at rest: the default, and its limit
Most applications encrypt data "at rest" — the database itself is encrypted on disk, so if someone steals the physical drive or a database backup, they can't read it without the encryption key. This is table stakes; AWS, GCP, and every managed database provider offer it essentially for free, and there's no good reason not to have it.
The limit: encryption at rest protects against the disk being stolen. It does not protect against a compromised application server, an over-privileged database credential, or an engineer with production database access reading clinical notes they have no business reading. If your application code can decrypt the field to display it, so can anyone who compromises that application code or that database connection.
For a lot of data, that's a perfectly acceptable risk profile. For a clinician's private notes about a patient — the specific, sensitive kind of data Slotwise handles — it's a wider blast radius than we wanted to accept.
Client-side encryption: narrower, and harder to build
Client-side encryption moves the encryption step into the browser, before the data is transmitted at all. On Slotwise, a clinician's note is encrypted with AES-256 on their device, and what reaches our servers — and sits in our database — is already ciphertext. We never hold the plaintext, and we never hold a key that could decrypt it server-side.
What this actually buys you:
A database breach reveals nothing readable. If our database were compromised outright, an attacker gets encrypted blobs, not clinical notes. There's no server-side key to steal that would unlock them.
A compromised application server can't read historical data either. Because decryption happens client-side with a key derived from something the user holds (not stored on our servers), even full control of the backend doesn't retroactively expose notes that were already encrypted and stored.
It closes off an entire category of insider-risk questions. "Could an engineer at Teamseven read a patient's clinical notes?" has a straightforward answer: no, not without the same key material the clinician holds, which we don't have.
What it costs you, and why most products don't do it:
Server-side search and reporting mostly stop working. If the server can't decrypt the data, it can't run a WHERE notes LIKE '%diabetes%' query, generate a searchable index, or power most reporting features without redesigning them to work over encrypted or selectively-decrypted data. This is the real reason most SaaS products don't do this by default — it's a genuine feature tradeoff, not just extra engineering effort.
Key management becomes the hard problem. If the user loses the key (a lost device, a forgotten recovery phrase), the data is unrecoverable — that's the whole point of the model, but it means the key-recovery UX has to be designed carefully, because "we can't get your data back" is a real support conversation you'll eventually have.
It has to be built in from the start. Retrofitting client-side encryption onto a system that was built assuming the server can read everything usually means redesigning the data model, not adding a library. This is not a feature you bolt on in a later sprint.
How we actually decided, and how you should too
The decision isn't "client-side encryption is more secure, so always use it." It's a question of what specific data you're protecting and from whom.
Use server-side encryption at rest as your floor, always. There's no argument against it — it's cheap, standard, and protects against the most common real-world breach vector (stolen backups, misconfigured storage).
Add client-side encryption when the data is narrow, sensitive, and doesn't need server-side processing. Clinical notes fit this well: a clinician writes a note, reads their own past notes, and that's essentially the entire access pattern. There's no need for the server to search inside the note text or generate analytics from its contents, so the searchability tradeoff costs nothing in practice.
Don't reach for client-side encryption on data you need to query, aggregate, or report on server-side. Appointment times, booking status, billing records — Slotwise keeps these server-side encrypted at rest but not client-side encrypted, because the product genuinely needs to query and aggregate them, and the sensitivity profile is different from a clinical note's free-text content.
The honest engineering question to ask before choosing either: what does the server actually need to do with this specific field? If the answer is "nothing except store it and hand it back to the same user later," client-side encryption costs you almost nothing in lost functionality and buys you a real reduction in blast radius. If the server needs to search it, aggregate it, or act on it, server-side encryption at rest — done properly, with tight access controls around the decryption path — is usually the right level.
Muhammad Nabeel is the co-founder of Teamseven. We built Slotwise, a live healthcare scheduling SaaS with AES-256 client-side encrypted clinical notes. If you're deciding how to handle sensitive data in a healthcare or clinical product, let's talk through the actual access pattern before defaulting to either model.