
Step by Step Guide to solve n8n SQLite database is locked
Who this is for: This guide is for n8n administrators and developers who run production‑grade workflows on the built‑in SQLite database and encounter lock contention. For a complete guide on managing SQLite in n8n, including errors, performance, and migration, check out our n8n SQLite pillar guide.
Quick Analysis
- Enable Write‑Ahead Logging (WAL)
- Raise the SQLite busy timeout (≥ 5000 ms)
- Serialize overlapping workflows (e.g., “Execute Workflow” node, queue‑based triggers)
- Restart n8n to apply the changes
If the problem persists, follow the detailed troubleshooting steps below.
Why n8n throws “SQLite database is locked” during concurrent workflows
Micro‑summary: This section explains the core reasons SQLite can become a bottleneck when multiple workflows write at the same time.
| Root Cause | Manifestation in n8n | Why it locks the DB |
|---|---|---|
| Simultaneous write transactions | Two or more executions attempt INSERT/UPDATE/DELETE together |
SQLite allows only one writer; the first obtains an exclusive lock, blocking the rest until commit |
| Long‑running transactions | A workflow performs many API calls before committing | The lock is held for the whole transaction, increasing contention |
Default journal mode (DELETE) |
No explicit WAL configuration | DELETE locks the whole file for writes, causing more collisions |
| Insufficient busy‑timeout | Immediate “database is locked” after a short wait | SQLite returns SQLITE_BUSY once the timeout (default ≤ 5 s) expires |
| Multiple n8n instances sharing the same DB file | Horizontal scaling without an external DB | Each instance competes for the same file lock, leading to frequent failures |
EEFA note: Treat the SQLite file as a single‑process resource in production. For true parallelism, migrate to PostgreSQL or MySQL.
Diagnostic checklist
Micro‑summary: Run these quick checks to confirm the source of the lock.
1. Identify overlapping workflows
Open Execution → List in the UI, filter by Status = “Running”, and note overlapping timestamps.
2. Inspect SQLite lock settings
# Show the current busy timeout (ms) sqlite3 ~/.n8n/database.sqlite "PRAGMA busy_timeout;"
# Show the active journal mode sqlite3 ~/.n8n/database.sqlite "PRAGMA journal_mode;"
3. Search logs for lock errors
grep -i "database is locked" ~/.n8n/logs/*.log
4. Verify single‑process access
ps aux | grep n8n # should list only one n8n process
5. Review workflow design for parallel triggers
Look for “Execute Workflow” or “Webhook” nodes that may fire the same workflow simultaneously.
If any check reveals concurrency, move to the resolution steps. Explore fixes for database opening errors in SQLite and related connection problems in n8n.
Resolution steps
1. Switch SQLite to Write‑Ahead Logging (WAL)
WAL lets readers continue while a writer holds a lock, reducing contention.
sqlite3 ~/.n8n/database.sqlite <<'SQL' PRAGMA journal_mode=WAL; SQL
sqlite3 ~/.n8n/database.sqlite <<'SQL' PRAGMA wal_autocheckpoint=1000; -- checkpoint after 1 000 pages SQL
EEFA: WAL creates
-waland-shmcompanion files. Include them in your backup routine.
2. Increase the busy timeout
Tell SQLite to wait longer before aborting a write attempt.
// ~/.n8n/config
{
"sqliteBusyTimeout": 10000 // 10 seconds
}
Or via an environment variable (Docker/K8s):
export N8N_SQLITE_BUSY_TIMEOUT=10000
3. Serialize workflow execution
a. Queue‑based triggers
Use the built‑in Queue node or an external broker (Redis, RabbitMQ) to serialize jobs.
{
"type": "n8n-nodes-base.queue",
"parameters": {
"mode": "FIFO",
"maxConcurrency": 1,
"retryOnFail": true
}
}
b. Rate‑limit “Execute Workflow”
{
"type": "n8n-nodes-base.executeWorkflow",
"parameters": {
"maxConcurrent": 1
}
}
4. Shorten transaction windows
Wrap only the essential DB writes in a transaction and commit immediately. Understand how connection timeouts and database locks affect your SQLite workflows in n8n.
// Custom Function node – minimal transaction
const db = await this.getDb();
await db.run('BEGIN TRANSACTION;');
await db.run(
'INSERT INTO execution_entity (id, data) VALUES (?, ?);',
[id, json]
);
await db.run('COMMIT;');
5. Migrate to an external RDBMS for high‑throughput workloads
If lock contention persists, switch to PostgreSQL or MySQL.
docker run -d \ -e DB_TYPE=postgresdb \ -e DB_POSTGRESDB_HOST=pg.example.com \ -e DB_POSTGRESDB_PORT=5432 \ -e DB_POSTGRESDB_DATABASE=n8n \ -e DB_POSTGRESDB_USER=n8n_user \ -e DB_POSTGRESDB_PASSWORD=strongPassword \ n8nio/n8n
EEFA: Export the SQLite DB (
sqlite3 .dump) and import it into the target DB. Test in a staging environment first.
Real‑world troubleshooting scenarios
Micro‑summary: Common patterns and their targeted fixes.
| Scenario | Symptom | Fix |
|---|---|---|
| Long‑running API call inside a workflow | Lock held > 30 s, subsequent runs fail instantly | Move the API call to a sub‑workflow triggered asynchronously, releasing the DB lock early |
| Multiple n8n containers sharing a volume | Random lock spikes after scaling | Use a central PostgreSQL DB instead of shared SQLite, or limit scaling to a single replica |
| Backup script runs during peak traffic | Backup fails with “database is locked” | Run backup with sqlite3 ... ".backup backup.db" after setting a longer timeout, or schedule during off‑peak windows |
| WAL enabled but locks remain | Errors persist despite WAL | Ensure checkpointing runs (PRAGMA wal_checkpoint(FULL);) and that the filesystem supports shared‑memory files (.shm). NFS can break WAL – switch to local storage |
Handy one‑liners you can copy‑paste
Enable WAL & set timeout in a single command
sqlite3 ~/.n8n/database.sqlite "PRAGMA journal_mode=WAL; PRAGMA busy_timeout=10000;"
Docker‑compose snippet for environment variables
services:
n8n:
image: n8nio/n8n
environment:
- DB_TYPE=sqlite
- DB_SQLITE_BUSY_TIMEOUT=10000 # ms
- DB_SQLITE_JOURNAL_MODE=WAL
volumes:
- ./n8n:/home/node/.n8n
Queue node configuration (UI JSON)
{
"type": "n8n-nodes-base.queue",
"parameters": {
"mode": "FIFO",
"maxConcurrency": 1,
"retryOnFail": true
}
}
Next steps & related topics
- Migrate n8n to PostgreSQL for enterprise‑grade concurrency – see the sibling page “n8n PostgreSQL migration guide”.
- Implement exponential back‑off retries on nodes that write to the DB, reducing immediate contention.
- Monitor SQLite lock statistics with
PRAGMA lock_status;and integrate alerts into your observability stack. - Check strategies to recover from transaction failures and other connection-related SQLite issues in n8n.
Conclusion
SQLite’s single‑writer architecture makes it vulnerable to lock contention when multiple n8n workflows write concurrently. By enabling WAL, raising the busy timeout, and serializing overlapping executions, you eliminate most production‑grade lock errors without changing the underlying data model. For workloads that consistently exceed SQLite’s concurrency limits, the proven path is to migrate to PostgreSQL or MySQL, where true parallel writes are natively supported. Apply the steps above, restart n8n, and verify that lock errors disappear—your workflows will run reliably at scale.



