The next evolution of SQLite is here! Read Announcement
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.
Encryption at rest is a requirement for:
We support two industry-standard algorithms:
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.
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;
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μs | 9.41μs | 0.2% |
5,000 (500K) | 9.48μs | 9.60μs | 1.3% |
100,000 (1M) | 9.49μs | 9.88μs | 4.1% |
50,000 (5M) | 12.51μs | 13.07μs | 4.5% |
100,000 (10M) | 12.75μs | 13.45μs | 5.5% |
150,000 (15M) | 12.80μs | 13.50μs | 5.5% |
Write Benchmarks:
Iterations (Rows) | Latency (Non-Encrypted DB) | Latency (Encrypted DB) | Overhead |
---|---|---|---|
1,000 (100K) | 6.29μs | 7.09μs | 12.7% |
5,000 (500K) | 6.81μs | 7.45μs | 9.4% |
100,000 (1M) | 7.07μs | 7.90μs | 11.8% |
50,000 (5M) | 9.85μs | 11.10μs | 12.7% |
100,000 (10M) | 10.98μs | 12.51μs | 13.9% |
150,000 (15M) | 10.56μs | 11.99μs | 13.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.24s | 5.33s | 1.7% |
5,000 (500K) | 25.80s | 25.92s | 0.5% |
10,000 (1M) | 50.74s | 51.69s | 1.9% |
50,000 (5M) | 303.48s | 308.67s | 1.7% |
100,000 (10M) | 622.37s | 630.30s | 1.3% |
150,000 (15M) | 905.50s | 930.97s | 2.8% |
The benchmark code is available here.
Future plans include:
ATTACH
statement support for encrypted databasesPer-page encryption delivers enterprise security without performance penalties. Deploy confidently anywhere: in the cloud, on a server, or on-device.