How Much Does Encrypting HomeBudget+'s Database Actually Cost?

How Much Does Encrypting HomeBudget+’s Database Actually Cost?

Von am 16.09.2026

When I added local database encryption to HomeBudget+ this semester, I made the decision mostly on principle: a personal finance app should protect its data if the phone is lost, so the SQLite database is encrypted with SQLCipher. What I hadn’t actually measured was what that decision costs in performance. This article is that measurement — and a lesson in why the first result I got was wrong.

First attempt: a laptop simulation

I first tested this in Python on my own computer, using a real SQLCipher build (sqlcipher3-binary) compared against Python’s plain sqlite3 module, both running the same schema as HomeBudget+’s expenses table. Encryption came out 99% to 141% slower on writes at larger row counts.

That result made sense on its own, but it had an obvious problem: it never touched an actual phone, or the actual plugin (@capacitor-community/sqlite) HomeBudget+ uses. So I built a temporary benchmark screen directly inside the app to test it for real.

First real-device result — and a result that didn’t add up

Figure 1: first in-app benchmark run, before fixing the methodology.

RowsOperationPlain (ms)Encrypted (ms)Overhead
500insert308.9245.8-20%
500selectAll32.723.9-27%
500selectFiltered8.97.1-20%
500update13.66.8-50%
2000insert687.6622.4-9%
2000selectAll81.967.5-18%
2000selectFiltered11.410.0-12%
2000update7.68.0+5%
5000insert1501.61458.6-3%
5000selectAll132.0116.3-12%
5000selectFiltered18.616.5-11%
5000update9.29.4+2%

When I added local database encryption to HomeBudget+ this semester, I made the decision mostly on principle: a personal finance app should protect its data if the phone is lost, so the SQLite database is encrypted with SQLCipher. What I hadn’t actually measured was what that decision costs in performance. This article is that measurement — and a lesson in why the first result I got was wrong.

First attempt: a laptop simulation

I first tested this in Python on my own computer, using a real SQLCipher build (sqlcipher3-binary) compared against Python’s plain sqlite3 module, both running the same schema as HomeBudget+’s expenses table. Encryption came out 99% to 141% slower on writes at larger row counts.

That result made sense on its own, but it had an obvious problem: it never touched an actual phone, or the actual plugin (@capacitor-community/sqlite) HomeBudget+ uses. So I built a temporary benchmark screen directly inside the app to test it for real.

First real-device result — and a result that didn’t add up

Finding the actual bug

The benchmark had two real problems. First, each configuration only ran once — a single slow moment (a background OS task, a garbage collection pause) could swing a result by tens of percent with no way to average it out. Second, the plain database was always benchmarked first and the encrypted one always second, every single time. If the very first SQLite connection opened in a test run pays a one-time “cold start” cost — for the native bridge, not for encryption — that cost always lands on whichever database goes first. Since plain always went first, plain was always the one absorbing a penalty that had nothing to do with encryption.

I fixed this three ways: added a throwaway warm-up connection before any timed run, repeated each configuration three times instead of once, and alternated which database went first on each repeat so the ordering effect would cancel out instead of consistently favoring one side.

Second real-device result

Figure 2: same benchmark, same phone, after fixing warm-up, repeats, and ordering.

RowsOperationPlain (ms)Encrypted (ms)Overhead
500insert203.7181.7-11%
500selectAll24.121.5-11%
500selectFiltered6.25.7-7%
500update8.07.5-7%
2000insert614.4597.9-3%
2000selectAll56.752.7-7%
2000selectFiltered9.912.3+24%
2000update8.09.1+13%
5000insert1376.11368.2-1%
5000selectAll121.9125.6+3%
5000selectFiltered17.117.3+1%
5000update10.09.2-8%

With the corrected methodology, the numbers moved to a believable range: mostly within about 10% either side of zero, with two outliers around +24% and +13% for the 2,000-row filtered select and update. That’s a mix of small real overhead and ordinary measurement noise — not a systematic, one-directional effect anymore.

Checking this against the people who actually built SQLCipher

SQLCipher’s own performance documentation states it directly:

“It’s not unusual to see as little as 5-15% overhead for SQLCipher encryption.” — SQLCipher Performance Optimization guide, zetetic.net

The corrected real-device numbers are small in magnitude compared to the Python results – but they are not consistently slower. Several readings came out negative (encrypted appearing faster), especially at 5,000 rows, where every operation landed within about 10% of zero in either direction. That is not evidence that encryption speeds anything up; it means that at this scale, on this device, ordinary measurement noise (background OS activity, scheduling jitter) is close to the same size as whatever real overhead exists, so three repeats per configuration cannot reliably tell which direction the true effect points. SQLCipher’s own guidance also notes that overhead “can vary significantly based on… platform” – modern phones often have hardware-accelerated AES built into the chip, which can make the real cost far smaller than the general 5-15% figure. The Python numbers from the first attempt (99-141%, always slower) are a different story: consistent and one-directional, which is a signal that the laptop simulation was measuring something other than ordinary SQLCipher overhead – most likely a difference between the Python build of SQLCipher and the native Android build the app actually uses, rather than anything specific to HomeBudget+.

The same SQLCipher performance page also states this, which reframes the whole experiment:

“Do NOT repeatedly open and close connections. Key derivation is very expensive, by design.” — SQLCipher Performance Optimization guide, zetetic.net

Every benchmark run in this article opens a brand new database connection for every single test. That means each encrypted measurement pays a full key-derivation cost that a real app, which opens its database once at startup and keeps the connection open, never pays more than once, ever. HomeBudget+ itself opens its one encrypted connection a single time when the app starts. The overhead numbers in this article, even the corrected ones, are closer to a worst case for how the app actually behaves than to how it behaves in practice.

What I learned

The result that should have been suspicious was the first one, and I’m glad it was flagged before it went in a report: “encryption made it faster” doesn’t have a mechanism behind it, and a result with no plausible mechanism is a reason to check the test, not the theory. The actual bug wasn’t encryption, or SQLite, or the phone — it was a benchmark that ran once, in a fixed order, with no warm-up, which is a classic way to accidentally measure your own test harness instead of the thing you’re testing.

The second lesson came from reading SQLCipher’s own documentation after the fact instead of before: it already explained why my first numbers looked the way they did (repeated connection opens inflate the apparent cost), and it explicitly warned that real-world overhead depends heavily on the platform – which matches finding numbers too close to zero to confidently compare against a general 5-15% figure. Checking primary sources earlier would have saved a round of confusion, and would have told me in advance that a fixed-order, single-run benchmark was going to be unreliable for this specific library.

Sources

SQLCipher Performance Optimization: https://www.zetetic.net/sqlcipher/performance

About SQLCipher: https://www.zetetic.net/sqlcipher/about/

sqlcipher3 (Python bindings used in the first attempt): https://github.com/coleifer/sqlcipher3

Capacitor Community SQLite plugin (what HomeBudget+ actually uses on-device): https://github.com/capacitor-community/sqlite

Beitrag kommentieren

(*) Pflichtfeld