documentation/concepts/write-ahead-log.md
import Screenshot from "@theme/Screenshot"
Write-Ahead Log (WAL) records all changes before applying them to storage. This enables concurrent writes, crash recovery, and replication.
WAL is enabled by default and recommended for all tables.
| Capability | Description |
|---|---|
| Concurrent writes | Multiple clients can write simultaneously without blocking |
| Crash recovery | Committed data is never lost — replay from log after restart |
| Replication | WAL enables high availability and disaster recovery |
| Out-of-order handling | Late-arriving data is merged efficiently |
| Deduplication | Enables DEDUP UPSERT KEYS |
In QuestDB Enterprise, WAL segments are sent to object storage immediately on commit, enabling real-time replication to standby nodes.
WAL is enabled by default for partitioned tables:
CREATE TABLE prices (
ts TIMESTAMP,
ticker SYMBOL,
price DOUBLE
) TIMESTAMP(ts) PARTITION BY DAY;
-- This is a WAL table (default)
You can be explicit with the WAL keyword:
CREATE TABLE prices (...)
TIMESTAMP(ts) PARTITION BY DAY WAL;
WAL requires partitioning. Non-partitioned tables cannot use WAL.
| Table creation method | Default partitioning | WAL enabled? |
|---|---|---|
SQL CREATE TABLE without PARTITION BY | None | No |
SQL CREATE TABLE with PARTITION BY | As specified | Yes |
| ILP auto-created tables | PARTITION BY DAY | Yes |
-- Non-partitioned = no WAL (not recommended for time-series)
CREATE TABLE static_data (key VARCHAR, value VARCHAR);
-- Partitioned = WAL enabled (recommended)
CREATE TABLE prices (...)
TIMESTAMP(ts) PARTITION BY DAY;
If you need WAL features (concurrent writes, replication, deduplication),
always specify PARTITION BY when creating tables via SQL.
Check if a table uses WAL:
SELECT name, walEnabled FROM tables() WHERE name = 'prices';
Check WAL table status:
SELECT * FROM wal_tables();
If WAL transactions are suspended (rare), resume them:
ALTER TABLE prices RESUME WAL;
When data is written to a WAL table:
This decouples the commit (fast) from storage application (background), enabling high write throughput.
<Screenshot alt="Diagram showing the sequencer allocating txn numbers to events chronologically" title="The sequencer allocates unique transaction numbers and serves as the single source of truth." height={435} src="images/docs/concepts/wal_sequencer.webp" width={745} />
<Screenshot alt="Diagram showing the WAL job application and WAL collect events and commit to QuestDB" title="The WAL apply job collects transactions sequentially for writing to storage." height={435} src="images/docs/concepts/wal_process.webp" width={745} />
WAL behavior can be tuned via server configuration:
cairo.wal.enabled.default — WAL enabled by default (default: true)To convert an existing table between WAL and non-WAL:
ALTER TABLE prices SET TYPE WAL;
-- Requires database restart to take effect
See ALTER TABLE SET TYPE for details.