Backend Selection Guide¶
pgqrs supports multiple storage backends, giving you flexibility to choose the right database for your use case.
Supported Backends¶
| Backend | DSN Format | Cargo Feature |
|---|---|---|
| PostgreSQL | postgresql://host/db |
postgres (default) |
| SQLite | sqlite:///path/to/file.db |
sqlite |
| Turso | turso:///path/to/file.db |
turso |
Decision Matrix¶
| Scenario | Recommended Backend | Why |
|---|---|---|
| Production with multiple workers | PostgreSQL | Full concurrency, no writer conflicts |
| CLI tools & scripts | SQLite / Turso | Zero-config, embedded, portable |
| Testing & prototyping | SQLite / Turso | Fast setup, no external dependencies |
| Embedded applications | SQLite / Turso | Single-file database, no server required |
| High write throughput | PostgreSQL | SQLite/Turso allow only 1 writer at a time |
| Distributed systems | PostgreSQL | Multiple processes can connect simultaneously |
PostgreSQL¶
PostgreSQL is the production-ready choice for most deployments.
Advantages¶
- Unlimited concurrent workers: Multiple producers and consumers can operate simultaneously
- Connection pooling: Works with pgBouncer and pgcat for connection scaling
- SKIP LOCKED: Efficient concurrent job fetching without conflicts
- Proven at scale: Handles millions of messages and large teams
When to Use¶
- Production workloads
- Multiple worker processes
- Distributed systems
- High write throughput requirements
DSN Examples¶
postgresql://localhost/mydb
postgresql://user:password@host:5432/database
postgres://localhost/mydb?sslmode=require
SQLite¶
SQLite is a zero-config embedded option for simpler deployments.
Advantages¶
- No server required: Database is a single file
- Zero configuration: No setup, no maintenance
- Portable: Database file can be copied/moved easily
- Fast for reads: Excellent read performance
Limitations¶
Concurrency Constraints
SQLite uses database-level locks. Only one writer can operate at a time.
With many concurrent writing processes, you may experience:
- Lock contention errors (
SQLITE_BUSY) - Starvation where some processes wait indefinitely
- Reduced throughput as writers queue up
See SkyPilot's detailed analysis of SQLite concurrency issues.
pgqrs Mitigations¶
pgqrs automatically configures SQLite for the best possible concurrency:
- WAL mode: Enables concurrent reads during writes
- 5000ms busy timeout: Retries locks instead of failing immediately
- Foreign key enforcement: Data integrity maintained
When to Use¶
- CLI tools and single-process scripts
- Testing and prototyping
- Embedded applications
- Development environments
- Desktop applications
DSN Examples¶
sqlite:///path/to/database.sqlite
sqlite:///var/lib/myapp/queue.db
sqlite::memory: # In-memory database (testing only)
Turso¶
Turso provides SQLite-compatible local storage with enhanced features.
Advantages¶
- SQLite-compatible: Drop-in replacement for SQLite with enhancements
- No server required: Database is a single file, just like SQLite
- Zero configuration: No setup, no maintenance
- Portable: Database file can be copied/moved easily
- Fast for reads: Excellent read performance
Limitations¶
Concurrency Constraints
Turso uses database-level locks (same as SQLite). Only one writer can operate at a time.
With many concurrent writing processes, you may experience:
- Lock contention errors (
SQLITE_BUSY) - Starvation where some processes wait indefinitely
- Reduced throughput as writers queue up
See SkyPilot's detailed analysis of SQLite concurrency issues.
pgqrs Mitigations¶
pgqrs automatically configures Turso for the best possible concurrency:
- WAL mode: Enables concurrent reads during writes
- 5000ms busy timeout: Retries locks instead of failing immediately
- Foreign key enforcement: Data integrity maintained
When to Use¶
- CLI tools and single-process scripts
- Testing and prototyping
- Embedded applications
- Development environments
- Desktop applications
DSN Examples¶
Cargo Feature Configuration¶
Rust¶
[dependencies]
# PostgreSQL only (default)
pgqrs = "0.13.0"
# SQLite only
pgqrs = { version = "0.13.0", default-features = false, features = ["sqlite"] }
# Turso only
pgqrs = { version = "0.13.0", default-features = false, features = ["turso"] }
# All backends
pgqrs = { version = "0.13.0", features = ["full"] }
Python¶
The Python package includes both backends by default.
API Compatibility¶
All backends implement the same Store trait, so your application code remains unchanged:
// Works with all backends!
async fn process_jobs(store: &impl pgqrs::Store) -> Result<(), pgqrs::Error> {
pgqrs::dequeue()
.from("tasks")
.handle(|msg| async move {
println!("Processing: {:?}", msg.payload);
Ok(())
})
.execute(store)
.await
}
Switch backends by changing your DSN: