# CipherStash now integrates with Supabase

*Published on 2026-07-09T00:00:00.000Z*

*By Dan Draper — CEO and Founder*

Encrypt sensitive fields in your Supabase database without losing query capabilities. Searchable field-level encryption, identity-bound keys, and cryptographic audit trails.

## Content

*Today we're launching the CipherStash integration for Supabase.*

Developers love Supabase: it’s the open-source managed Postgres platform with an integrated suite of backend services, including Auth, Storage, Edge Functions, Realtime, and more. More than 9 million developers use Supabase to build and scale their applications.

CipherStash is the privacy layer for applications built on Supabase. It encrypts sensitive fields, and lets you search and join encrypted data without decrypting it. Audit logging, key management, and authentication are built in, so you don’t need to build encryption infrastructure from scratch.

With CipherStash, teams can secure sensitive data in Supabase and extend access control to AI agents, not just human users.

{% quote author="Bil Harmer" title="CISO, Supabase" avatar="/images/blog/author-bil-harmer.jpg" %}
I've spent over 15 years searching for this. CipherStash is the first platform I've seen that lets engineering teams ship encryption without trading away the database.
{% /quote %}

With the Supabase integration, you add field-level encryption to any Supabase project through the encrypted Supabase SDK wrapper.
Run `npx stash init --supabase` to get set up, nominate the columns you want to protect, and keep your queries the same.

- Works with Supabase.js, Prisma Next, Drizzle, or plain SQL through `pg`
- Integrates with Supabase Auth, Clerk, Okta, and Auth0
- Supports `WHERE`, `LIKE`, `ORDER BY`, `JOIN`, and `GROUP BY` over encrypted columns
- Has query overhead typically less than 10ms (see [benchmarks](https://github.com/cipherstash/benches))

{% youtube id="SHa7XTeHYK8" title="Introducing the official CipherStash and Supabase integration" caption="The integration, in 33 seconds." /%}

## Built for agents, not just humans

Application security grew up around one kind of user: a human behind a session. Agents break that model. They act on behalf of users, chain tools together, write to logs and traces, and can be steered by untrusted input, all while needing real access to your data to be useful. The tempting shortcut is to hand the agent broad credentials and hope for the best.
When IBM studied last year's breaches of AI systems, [97% of the organizations hit lacked proper access controls](https://newsroom.ibm.com/2025-07-30-ibm-report-13-of-organizations-reported-breaches-of-ai-models-or-applications,-97-of-which-reported-lacking-proper-ai-access-controls).

CipherStash moves access control from the perimeter to the data itself. Sensitive values are encrypted in your application before being saved to the database, and they can only be decrypted again by an authorized user.
Data remains queryable, while add [just milliseconds](https://github.com/cipherstash/benches) of overhead.

AI Agents get their own decryption keys, separate from the users who drive them. Access policies that your team defines are embedded in encrypted values, so an agent can only ever see data it is explicitly allowed to read, and every access is logged, so security teams have the tools they need if anything ever goes wrong.

## How it works

CipherStash encrypted search is built on the [Encrypted Query Language](/docs/reference/eql) (EQL), which can be installed into any Supabase Database. Like regular Postgres, EQL provides a set of common data types and functions, but is designed for working with encrypted data.

Use EQL types for table columns you want to protect. 
For example, to create a users table with encrypted `email` and `profile` fields:

```sql
CREATE TABLE users (
  id         serial PRIMARY KEY,
  created_at timestamp,
  -- sensitive data
  email      eql_v3_text_search,
  profile    eql_v3_json
);
```

EQL types are _self-describing_. Each type name contains the EQL version, underlying data type and optional "modifiers" indicating that encrypted search is available.

{% figure src="/images/blog/anatomy-of-eql-type.png" alt="Anatomy of an EQL type: eql_v3_text_search, broken into eql_v3 (version), text (decrypted type), and search (optional search modifier)" width="full" /%}

For example:

* Use `eql_v3_date_eq` to filter encrypted dates with `WHERE` 
* Use `eql_v3_integer_ord` to filter and sort encrypted integers with `WHERE` and `ORDER BY`  
* Use `eql_v3_text_search` for full-text search with approximate-`LIKE` filtering, `WHERE` clauses, and `ORDER BY`

Most types also support JOIN, GROUP BY, and UNION queries.
The [encrypted queries reference](https://cipherstash.com/docs/stack/cipherstash/encryption/queries) has the full list.

Once installed, you can add EQL columns from the Table Editor in the [Supabase Dashboard](https://supabase.com/dashboard), the same way you'd pick `text` or `int8`.

## Your database never sees your data

EQL describes how encryption should be used, but it doesn’t actually perform the encryption.
For that, [`@cipherstash/stack`](https://github.com/cipherstash/stack) to encrypt data in your application before saving it to the database. It comes with plugins for common ORMs and frameworks, including Supabase.js.

Import the encrypted Supabase wrapper from `@cipherstash/stack` and connect the same way you would with `supabase-js`:


```ts
import { encryptedSupabaseV3 } from '@cipherstash/stack/supabase'

// Reads your schema over DATABASE_URL to find the encrypted columns
const supabase = await encryptedSupabaseV3(supabaseUrl, supabaseKey)
```

Insert a value into an EQL column, and it will be automatically encrypted:

```ts
// Insert — the value is encrypted automatically
await supabase
  .from('users')
  .insert({ email: 'alice@example.com' })
```

Queries are encrypted too. The search term is encrypted before it leaves your app, and by default the results come back decrypted:

```ts
// Query — the search term is encrypted, results are decrypted for you
const { data } = await supabase
  .from('users')
  .select()
  .eq('email', 'alice@example.com')
```

Same API, same `.eq()`, `.like()`, and `.order()` you use today.
The plaintext and the keys never leave your environment, and they never reach us.

## FAQ

**Can CipherStash ever see my data, or my encryption keys?**
No, never. Encryption and decryption occur in your application, and keys are derived in your environment. Plaintext and keys never leave your control and never reach CipherStash.

**How well does it scale?**
Latency stays flat as data grows: exact-match lookups hold at ~0.1 ms, and range queries at ~0.5 ms, from 10k to 10M rows.{% fnref /%}

**What does migration look like?**
Install EQL on your Supabase database. Choose which columns you want to protect, then set their encryption type. Encrypt values in your app before saving them. You can update columns one at a time.

**Do I have to change how I write queries?**
No. Query encrypted columns with the same Supabase.js calls you use today.

**Do I need to run a KMS or a key vault?**
No. Key management is built in through [ZeroKMS](https://cipherstash.com/docs/stack/cipherstash/kms). If you want to own the root key, BYOK lets you root it in your own KMS.

**Does it work with Supabase Auth and Row-Level Security?**
Yes. It integrates with Supabase Auth and runs alongside RLS. It complements them; it does not replace them.

**I already use Row Level Security (RLS), do I need the CipherStash integration for Supabase?**
RLS and CipherStash do different things, and they work best when used together. RLS controls which rows someone can see, but the actual data is still unencrypted. If RLS is bypassed, for example through a leaked key, a misconfigured policy, or a compromised database, the plaintext is exposed. CipherStash encrypts the data and stores the keys separately, so even if someone gets around RLS, the data stays safe. Use RLS to control access and CipherStash to keep your data protected.

**Is there a free tier?**
Yes, there’s a free developer tier, so you can build encryption in from day one.

## Get started

Get started with the [Supabase Integration](https://supabase.com/partners/integrations/cipherstash) or run:

```sh
npx stash init --supabase
```

For more information see the [Supabase integration guide](https://cipherstash.com/docs/stack/cipherstash/encryption/supabase), browse the [source on GitHub](https://github.com/cipherstash/stack), or come and say hi in [Discord](https://discord.com/invite/5qwXUFb6PB).

{% footnote %}
Measured against a 10-million-row dataset. Methodology and raw results are in our open-source [benchmark suite](https://github.com/cipherstash/benches) ([full report](https://github.com/cipherstash/benches/blob/main/report/BENCHMARK_REPORT.md)).
{% /footnote %}

## Related blog posts

- [Encrypting Supabase data with CipherStash Stack](https://cipherstash.com/blog/encrypting-supabase-data-with-cipherstash-stack.md) — Drop-in field-level encryption for Supabase that keeps your queries working. Equality, LIKE, ranges and ordering — all over ciphertext, with the Supabase JS client you already use.
- [Introducing @cipherstash/stack](https://cipherstash.com/blog/introducing-cipherstash-stack.md) — Building blocks for Data Level Access Control in TypeScript
- [Adding CipherStash Stack to a Next.js + Supabase app](https://cipherstash.com/blog/adding-cipherstash-stack-to-nextjs-supabase.md) — A short, code-heavy walkthrough — add searchable field-level encryption to a Next.js + Supabase app with CipherStash Stack. Both App Router and Pages Router. Stack-first; no Protect.js.

