Introduction
SQLite gets dismissed as a "toy database" for web applications, but with the right configuration it can handle real production traffic. The secret weapon is WAL (Write-Ahead Logging) mode. Here's how I use it to power ViralVidVault — a video platform serving thousands of pages while cron jobs write new data concurrently.
The Problem: Readers Block Writers
In SQLite's default journal mode (DELETE), a write operation locks the entire database. If your cron job is inserting 200 videos, every web request that tries to read the database will wait. On a video platform, this is unacceptable.
The Solution: WAL Mode
WAL mode flips the locking model: readers never block writers, and writers never block readers. Multiple readers can access the database simultaneously while a single writer appends to a separate write-ahead log.
<?php
class Database
{
private \PDO $pdo;
public function __construct(string $dbPath)
{
$this->pdo = new \PDO("sqlite:{$dbPath}");
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
// Enable WAL mode for concurrent access
$this->pdo->exec('PRAGMA journal_mode=WAL');
// Additional performance pragmas
$this->pdo->exec('PRAGMA synchronous=NORMAL');
$this->pdo->exec('PRAGMA cache_size=-8000'); // 8MB cache
$this->pdo->exec('PRAGMA temp_store=MEMORY');
$this->pdo->exec('PRAGMA mmap_size=268435456'); // 256MB mmap
}
public function getPdo(): \PDO
{
return $this->pdo;
}
}
Understanding the Pragmas
| Pragma | Value | Effect |
|---|---|---|
journal_mode=WAL |
WAL | Enables Write-Ahead Logging |
synchronous=NORMAL |
NORMAL | Fsync at checkpoints only (safe for WAL) |
cache_size=-8000 |
8MB | Larger page cache for reads |
temp_store=MEMORY |
MEMORY | Temp tables in RAM |
mmap_size=268435456 |
256MB | Memory-map reads for speed |
Real-World Scenario
On ViralVidVault, here's what happens during a cron run:
Timeline:
|---- Web request (SELECT videos) ----|
|---- Cron job (INSERT 200 videos) ----|
|---- Web request (SELECT categories) ----|
|---- Web request (SELECT trending) ----|
Without WAL: Web requests WAIT for cron INSERT to finish
With WAL: Everything runs concurrently, zero blocking
Measuring the Difference
I benchmarked both modes with Apache Bench while running a simulated cron insert:
# Simulate cron writing 500 rows
php simulate_cron_write.php &
# Simultaneously benchmark reads
ab -n 1000 -c 10 https://viralvidvault.com/
Results
| Metric | DELETE mode | WAL mode | Improvement |
|---|---|---|---|
| Avg response | 245ms | 92ms | 62% faster |
| P99 response | 1,200ms | 180ms | 85% faster |
| Failed requests | 12 | 0 | 100% |
| Throughput | 38 req/s | 105 req/s | 2.7x |
The P99 improvement is the most striking. Without WAL, tail latency spikes during writes. With WAL, response times stay consistent.
WAL Checkpointing
WAL files grow until a checkpoint merges them back into the main database. SQLite auto-checkpoints at 1000 pages by default. You can also trigger manual checkpoints:
// After cron completes all writes
$db->exec('PRAGMA wal_checkpoint(TRUNCATE)');
Caveats
- WAL mode is persistent — set it once, it sticks across connections
- One writer at a time — WAL doesn't allow concurrent writers (use transactions wisely)
- Network filesystems — WAL requires shared memory, won't work on NFS
-
WAL files — You'll see
.db-waland.db-shmfiles alongside your database
When SQLite + WAL Is Enough
For sites like viralvidvault.com with:
- Thousands of daily page views (not millions)
- Single-server deployment
- Read-heavy workload (95%+ reads)
- Periodic batch writes (cron every few hours)
SQLite with WAL mode is not just adequate — it's optimal. Zero config, zero maintenance, zero external dependencies. The entire database is a single file you can back up with cp.
Key Takeaways
- Always enable WAL mode for web-facing SQLite databases
- Set
synchronous=NORMALfor WAL (it's safe and faster) - Use
cache_sizeandmmap_sizepragmas for read performance - Checkpoint after batch writes to control WAL file growth
- SQLite + WAL handles real production traffic — don't dismiss it
This powers ViralVidVault — your vault of viral videos from around the world.
Top comments (0)