The next evolution of SQLite is here! Read Announcement

Introducing Fast, Native Encryption in Turso Database

Avinash SajjanshettyAvinash Sajjanshetty
Cover image for Introducing Fast, Native Encryption in Turso Database

Turso Database is SQLite rewritten in Rust. We're building full compatibility with SQLite and adding features it doesn't have, like encryption. SQLite doesn't include an official encryption feature, either through its core or bundled extensions.

Today, we're launching native encryption in Turso Database. We want Turso to run truly everywhere. Encryption makes this possible in environments where privacy, security, and integrity are paramount—and it's fast, adding as little as 6% read overhead and 14% write overhead.

#Turso Database Encryption

  • Data Integrity A page is the smallest unit of data that the database reads from or writes to disk. A typical size for a page is 4 KiB (4096 bytes). In Turso Database, each page is encrypted individually. This makes it difficult for an attacker to extract data from an encrypted database.
  • Run Databases Everywhere Modern apps deploy on edge devices, multi-cloud environments, and regions with varying security standards. Running databases across these diverse environments while maintaining high security requires encryption. And unlike SQLite, it's built right into Turso—no extensions needed.
  • Fully Open Source Our encryption implementation is transparent and auditable. No black boxes. You can verify exactly how your data is protected.

Encryption at rest is a requirement for:

  • Fintech apps: Regulatory requirements and sensitive financial data
  • Privacy-focused products: User trust depends on strong data protection
  • AI/ML applications: Training data and model outputs often contain sensitive information

#Encryption Algorithms

We support two industry-standard algorithms:

  • AEGIS: Extremely fast with better security features
  • AES-GCM: NIST-approved standard

Note that we only support AEAD algorithms as they provide both data protection and integrity. Authenticated encryption schemes also include a tag that acts like a checksum. This provides protection against data tampering and corruption.

#Technical Details

  • Page-level operation: Each page is encrypted and decrypted individually, on demand. A new cryptographically secure nonce is (re)generated every time we encrypt a page.
  • All the encryption metadata (the nonce and the tag) is stored in the page itself. We use SQLite's reserved space feature to allocate space on the page; this portion won't be used by the B-Tree.
  • Database and WAL files are encrypted on disk
  • Keys are never stored on disk – provided per connection, kept in memory only

#What's Encrypted

  • ✅ All database pages with your data
  • ✅ The database file
  • ✅ Write-Ahead Log (WAL) file
  • ❌ The database header (first 100 bytes)

#Usage

To use encryption, pass the --experimental-encryption flag. To get started, generate a secure 32-byte key in hex:

$ openssl rand -hex 32
2d7a30108d3eb3e45c90a732041fe54778bdcf707c76749fab7da335d1b39c1d

Specify the key and cipher at the time of database creation to use encryption:

$ tursodb --experimental-encryption "file:encrypted.db?cipher=aegis256&hexkey=2d7a30108d3eb3e45c90a732041fe54778bdcf707c76749fab7da335d1b39c1d"
> CREATE TABLE t(v);
> INSERT INTO t(v) VALUES (42);

Use the URI format when opening an encrypted database:

$ tursodb --experimental-encryption "file:encrypted.db?cipher=aegis256&hexkey=2d7a30108d3eb3e45c90a732041fe54778bdcf707c76749fab7da335d1b39c1d"
> SELECT * FROM t;

#Benchmarks

For smaller databases, encryption adds negligible overhead. With larger databases, we observe approximately 6% overhead for reads and 14% overhead for writes when using AEGIS-256. The benchmark uses a batch size of 100 and runs for n iterations. As n increases, the database size grows proportionally. Each batch contains a mix of read and write operations determined by a specified ratio. The results below use a read ratio of 75%.

Read Benchmarks:

Iterations (Rows)Latency (Non-Encrypted DB)Latency (Encrypted DB)Overhead
1,000 (100K)9.39μs9.41μs0.2%
5,000 (500K)9.48μs9.60μs1.3%
100,000 (1M)9.49μs9.88μs4.1%
50,000 (5M)12.51μs13.07μs4.5%
100,000 (10M)12.75μs13.45μs5.5%
150,000 (15M)12.80μs13.50μs5.5%

Write Benchmarks:

Iterations (Rows)Latency (Non-Encrypted DB)Latency (Encrypted DB)Overhead
1,000 (100K)6.29μs7.09μs12.7%
5,000 (500K)6.81μs7.45μs9.4%
100,000 (1M)7.07μs7.90μs11.8%
50,000 (5M)9.85μs11.10μs12.7%
100,000 (10M)10.98μs12.51μs13.9%
150,000 (15M)10.56μs11.99μs13.5%

An astute reader might notice that write latencies are lower than read latencies. This is because latency is measured after each operation in the batch, before the commit statement is executed. However, this is acceptable since we're only interested in measuring the encryption overhead.

Aggregated Total Time:

Iterations (Rows)Time (Non-Encrypted DB)Time (Encrypted DB)Overhead
1,000 (100K)5.24s5.33s1.7%
5,000 (500K)25.80s25.92s0.5%
10,000 (1M)50.74s51.69s1.9%
50,000 (5M)303.48s308.67s1.7%
100,000 (10M)622.37s630.30s1.3%
150,000 (15M)905.50s930.97s2.8%

The benchmark code is available here.

#What's Coming Next?

Future plans include:

  • Secure key derivation from passphrases
  • Encrypting existing SQLite/Turso databases
  • Rekeying for key rotation
  • ATTACH statement support for encrypted databases

Per-page encryption delivers enterprise security without performance penalties. Deploy confidently anywhere: in the cloud, on a server, or on-device.