Technical page
This page details how Debounce works under the hood.
A page about the recovery phrase can be found here.
Overview of cryptography
Debounce uses BCrypt (11 cost) to derive keys, and XChaCha20-poly1305 for encryption.
For data encryption, a master key is used. This key is encrypted by your derived password and the recovery phrase, and is stored on the server.
How data is encrypted
All data is encrypted with a master encryption key. This key is encrypted on the server and is decrypted client-side using either your password or recovery phrase.
The key is not directly derived from your password, which allows you to change your account password without re-encrypting all data.

Other than the reduce in complexity, the reason that only symmetrical algorithms were chosen (preventing collaborative features among separate Debounce accounts) was quantum resistance.
Offline access
Cached data like notes and journals are stored encrypted in IndexedDB. Offline functionality requires the browser to support service workers.
Tech stack
Debounce uses SvelteKit and Svelte 5 for the frontend, and Spring Boot with Kotlin for the backend. Data is stored in Postgres and cached in Redis.
Performance is enhanced with a service worker, and crypto work is moved to a web worker.
Efficiency / performance
Debounce (as is in the name) has a 200ms debounce timer on note edits (with a 1s "throttle"). When an edit gets queued, the note text is encrypted and then diffed with Google DMP, and the delta is sent to the server.
What runs on your browser
This is a part of package.json of the Debounce frontend:
"dependencies": {
"@rsocket/core": "^1.0.0-alpha.3",
"@rsocket/websocket-client": "^1.0.0-alpha.3",
"bcryptjs": "^2.4.3",
"buffer": "^6.0.3",
"comlink": "^4.4.1",
"crypto-browserify": "^3.12.0",
"crypto-js": "^4.2.0",
"diff-match-patch-ts": "^0.6.0",
"env": "^0.0.2",
"jszip": "^3.10.1",
"libsodium-wrappers": "^0.7.13",
"process": "^0.11.10",
"qrcode": "^1.5.4",
"rollup-plugin-visualizer": "^5.12.0",
"virtua": "^0.35.1",
}
Other packages that are integrated manually:
- @zerodevx/svelte-toast
Notification toast