Architecture
Storage
A B-tree with 4 KB pages; values are JSON-serialized, and larger ones (>~2 KB) spill into overflow pages. Each database is one .fdb file plus a WAL (.fdb.wal).
Crash recovery
After any crash — kill, SIGTERM, kernel panic, power loss — every committed transaction survives:
- The WAL is written ahead of the main file, fsynced on every commit.
- Recovery on
OpenDatabasereplays every committed transaction in increasing txID order. - The catalog (each B-tree's rootID, auto-increment counters, schema) is updated inside the WAL transaction, atomically with the data.
- Evicting a dirty page from the page cache never writes to the main file directly — that would violate the WAL invariant.
- Checkpoint flushes the page cache and truncates the WAL — in the background every 60 seconds, and on a clean
Close()/CloseAll().
Important for embedders: if the process exits without an explicit CloseAll() (or a per-database Checkpoint()) — a bare os.Exit, or an unhandled signal — the most recently committed but not-yet-checkpointed writes risk not making it into the main file on next open. As of v2.10, api.Server.CloseOnSignal() is available as an opt-in helper that subscribes to SIGINT/SIGTERM itself, calls CloseAll(), and re-delivers the signal.
Security
- Passwords — PBKDF2-HMAC-SHA256, 100,000 iterations, 16-byte salt.
- Constant-time compare for every credential check.
- Path-traversal protection via
validateDBName()—..,/, `` are rejected. - 16 MiB request body limit on auth-protected endpoints.
- RPC has a 60s read deadline and a limit on auth attempts.
- Configs containing an
api_keyare saved with0600permissions.
← Previous
Deployment