> ## Documentation Index
> Fetch the complete documentation index at: https://archie.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Field-level encryption stores selected columns as ciphertext in your database and returns them decrypted only to callers that prove authorization with a signed request.

Field-level encryption lets you mark individual fields as **private**. Archie encrypts those values before they are written to your database and, by default, returns them as ciphertext. A caller only sees the plaintext when it proves authorization by signing the request with your project's private key.

Use it for fields that must stay unreadable in the database itself — medical notes, government IDs, secrets — so a database dump, a backup, or direct database access never exposes them.

<Note>
  Encryption is **server-side**: Archie holds the keys and can decrypt on your behalf when a request is authorized. This protects your data at rest against dumps, backups, and direct database access. It is **not** end-to-end encryption — a compromise of the platform can read the data. Communicate this guarantee to your stakeholders before relying on it.
</Note>

## How it works at a glance

<Steps>
  <Step title="Mark a field as encrypted">
    In the [Data Model](/docs/features/backend/data-model/data-types), open a field's settings and turn on **Encrypted**. The flag is stored per field, per environment.
  </Step>

  <Step title="Generate the key pair">
    Under **Backend → App Services → Encryption**, generate the key pair for the active environment. The private key is shown **once** — save it. It is what authorizes decryption.
  </Step>

  <Step title="Write data normally">
    Send plaintext to your create and update mutations. Archie seals each encrypted field before it hits the database. Nothing changes in how you write.
  </Step>

  <Step title="Read data back">
    A normal read returns the encrypted value (ciphertext). To get the plaintext, the caller signs the request with the private key and sends three [decrypt headers](/docs/features/backend/app-services/encryption/reading-encrypted-data). Without a valid signature, the value stays ciphertext — the read never fails.
  </Step>
</Steps>

## What gets protected

Each encrypted value is sealed individually with **AES-256-GCM**. The key that encrypts your data (the data encryption key) is itself wrapped by a master key that never leaves the platform process — a pattern called envelope encryption. The result is that:

* The value stored in your database is an opaque, authenticated ciphertext.
* A database dump, backup, or read replica contains only ciphertext for those fields.
* Every value uses a fresh nonce, so identical plaintexts produce different ciphertexts.

## Enable encryption on a field

<Steps>
  <Step title="Open the field settings">
    In the **Data Model**, select the table and open the settings for the field you want to protect.
  </Step>

  <Step title="Turn on Encrypted">
    Toggle **Encrypted** on and save. Archie normalizes the column to a text type so it can hold the ciphertext envelope, which is larger than the plaintext.
  </Step>
</Steps>

Not every field can be encrypted. Archie rejects the toggle when it would break data integrity:

| Field kind                | Why it can't be encrypted                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------------- |
| Primary key               | Identifies the row; must stay readable and stable.                                              |
| Unique field              | Randomized ciphertext breaks uniqueness — the same input encrypts differently each time.        |
| Foreign key (either side) | Relationships are resolved on the stored value.                                                 |
| Generated field           | Computed by the database, not written by you.                                                   |
| Non-text field            | The ciphertext envelope is text; the column must be able to store it.                           |
| Short fixed-length text   | A `VARCHAR(n)` too small to hold the envelope would truncate it. Use `TEXT` or a longer length. |

<Warning>
  Turning encryption **on** for a field that already has data is not covered by the standard toggle — existing rows would stay in plaintext while new writes get sealed. Enable encryption on empty fields, or contact support about migrating a populated field.
</Warning>

## Generate the key pair

The key pair authorizes decryption. It is scoped to the **active environment** — each environment has its own.

<Steps>
  <Step title="Open the Encryption panel">
    Go to **Backend → App Services → Encryption**.
  </Step>

  <Step title="Generate">
    Click **Generate key pair**. Archie creates an Ed25519 key pair and provisions the data key for the environment.
  </Step>

  <Step title="Save the private key">
    The **private key is displayed once and never again**. Copy it and store it in a secret manager. Archie keeps only the public key, which it uses to verify signed requests.
  </Step>
</Steps>

<Warning>
  If you lose the private key, generate a new pair — but a new pair invalidates any request signed with the old one. Regenerating the key pair does not re-encrypt your data; it only changes what can authorize decryption going forward.
</Warning>

## Limitations

Because each value is encrypted with a fresh nonce, the ciphertext is not searchable or comparable. Archie enforces this rather than returning silently wrong results:

* Encrypted fields are **excluded from full-text search** — they never enter the search index.
* **Filtering, sorting, and aggregating** on an encrypted field is **rejected**, not ignored.
* Exact-match lookup on an encrypted field is not supported in this version.

Plan your data model so that fields you need to search, filter, or sort on stay unencrypted, and only the sensitive payload is private.

## FAQ

<AccordionGroup>
  <Accordion title="Can Archie read my encrypted data?">
    Yes. This is server-side encryption: the platform holds the keys and decrypts when a request is authorized. It protects against database dumps, backups, and direct database access — not against a platform compromise. It is not end-to-end encryption.
  </Accordion>

  <Accordion title="Do normal reads break when I encrypt a field?">
    No. A read without a decrypt signature returns the ciphertext instead of failing. Only a request that presents a valid signature gets the plaintext. See [Reading encrypted data](/docs/features/backend/app-services/encryption/reading-encrypted-data).
  </Accordion>

  <Accordion title="Is the key pair shared across environments?">
    No. The key pair is scoped to the environment you generated it in. Generate one per environment. Key material is never copied when you branch an environment.
  </Accordion>

  <Accordion title="Can I search or filter on an encrypted field?">
    No. Encrypted values use a fresh nonce each time, so they aren't comparable. Full-text search excludes them, and filter, sort, and aggregate on an encrypted field are rejected. Keep searchable fields unencrypted.
  </Accordion>

  <Accordion title="What happens if I lose the private key?">
    Generate a new key pair from the Encryption panel. The old private key stops working immediately. Your stored data is unaffected — only decryption authorization changes.
  </Accordion>
</AccordionGroup>
