← All articles
TutorialConfiguration

Paperclip Database Configuration

Paperclip uses SQLite by default — zero configuration, runs instantly. For larger teams or high-concurrency deployments, you can switch to PostgreSQL. Here's when to do which and how to configure both.

Deploy on Railway →

Default: SQLite

Out of the box, Paperclip stores everything in a SQLite database at:

$PAPERCLIP_DATA_DIR/db/paperclip.db

SQLite is a single-file database that requires zero setup. Paperclip creates it automatically on first start. For most deployments — including teams with 10–20 agents — SQLite works reliably.

When SQLite is fine:

  • Personal or small-team use
  • Single-server deployments
  • Up to ~50 concurrent agent runs
  • Read-heavy workloads

When to consider Postgres:

  • Multiple Paperclip instances sharing the same database
  • Very high write concurrency (100+ agents running simultaneously)
  • You need managed database backups, replication, or point-in-time recovery
  • You're already running Postgres infrastructure

PostgreSQL configuration

To use PostgreSQL instead of SQLite, set the DATABASE_URL environment variable:

DATABASE_URL=postgresql://username:password@host:5432/database_name

Local Postgres

# Install Postgres on Ubuntu
sudo apt install -y postgresql

# Create database and user
sudo -u postgres psql << 'EOF'
CREATE USER paperclip WITH PASSWORD 'your_password';
CREATE DATABASE paperclip OWNER paperclip;
GRANT ALL PRIVILEGES ON DATABASE paperclip TO paperclip;
EOF

# Set in .env
DATABASE_URL=postgresql://paperclip:your_password@localhost:5432/paperclip

Railway Postgres plugin

Railway provides managed Postgres that auto-connects to your service:

  1. In your Railway service, click + Add Plugin
  2. Select PostgreSQL
  3. Railway automatically injects DATABASE_URL as a service variable
  4. Restart your Paperclip service — it will use Postgres automatically

Supabase (free Postgres tier)

# From Supabase dashboard: Settings → Database → Connection String
DATABASE_URL=postgresql://postgres:[YOUR-PASSWORD]@db.[PROJECT].supabase.co:5432/postgres

Neon (serverless Postgres)

DATABASE_URL=postgresql://user:password@ep-example.us-east-2.aws.neon.tech/neondb?sslmode=require

Self-hosted Postgres with SSL

DATABASE_URL=postgresql://paperclip:password@db.yourdomain.com:5432/paperclip?sslmode=require

Connection pool settings

For high-concurrency deployments, configure the connection pool. Add these to your DATABASE_URL or set them as separate env vars:

# Maximum number of database connections
DATABASE_POOL_SIZE=10  # Default: 5

# Milliseconds to wait for a connection from the pool
DATABASE_POOL_TIMEOUT=30000  # Default: 30000 (30 seconds)

Running migrations

Paperclip runs database migrations automatically on startup. Control this behavior:

# Auto-apply without prompting (recommended for production)
PAPERCLIP_MIGRATION_AUTO_APPLY=true
PAPERCLIP_MIGRATION_PROMPT=never

When a new Paperclip version includes schema changes, these run on the next startup. The migration history is tracked in the database, so each migration only runs once.

Migration safety: Paperclip's migrations are additive — they add columns and tables but rarely drop them. Major version upgrades may include more significant schema changes; always check the release notes.

Database maintenance

SQLite maintenance

SQLite databases can grow fragmented over time. Run VACUUM periodically to reclaim space:

# While Paperclip is stopped (or use online VACUUM)
sqlite3 /opt/paperclip/data/db/paperclip.db "VACUUM;"

# Check database size and integrity
sqlite3 /opt/paperclip/data/db/paperclip.db "PRAGMA integrity_check;"
sqlite3 /opt/paperclip/data/db/paperclip.db "SELECT page_count * page_size / 1024 / 1024 AS 'Size (MB)' FROM pragma_page_count(), pragma_page_size();"

Postgres maintenance

With Postgres, regular maintenance is handled automatically by autovacuum. Monitor database size:

SELECT pg_size_pretty(pg_database_size('paperclip')) AS db_size;

-- Check table sizes
SELECT 
  relname AS table,
  pg_size_pretty(pg_total_relation_size(relid)) AS size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;

Migrating from SQLite to Postgres

There's no automated migration tool built into Paperclip yet. The safest approach for migrating an existing instance:

  1. Export your Paperclip data (export feature in the UI or API)
  2. Set up a fresh Paperclip instance with Postgres
  3. Import your data
  4. Verify all agents, issues, and settings transferred correctly

For a new deployment, just set DATABASE_URL from day one.

Database location in Docker

When using Docker Compose, the database is stored in a named volume:

volumes:
  - paperclip_data:/data

Paperclip's PAPERCLIP_DATA_DIR=/data puts the database at /data/db/paperclip.db inside the container. The volume persists across container restarts and removals.

Checking what database Paperclip is using

Look at startup logs:

journalctl -u paperclip --since "5 minutes ago" | grep -i "database\|sqlite\|postgres"

Or check the API health endpoint:

curl http://localhost:3100/api/health | jq '.database'

Common errors

SQLITE_BUSY: database is locked: Another process has the database open. Make sure only one Paperclip instance is running: ps aux | grep paperclip

FATAL: password authentication failed for user "paperclip": Wrong password in DATABASE_URL. Verify with: psql $DATABASE_URL -c "SELECT 1"

connect ECONNREFUSED 127.0.0.1:5432: Postgres isn't running. Check: sudo systemctl status postgresql

database "paperclip" does not exist: Create it first: createdb -U postgres paperclip

Ready to deploy?

Affiliate disclosure: this link may earn us a commission at no extra cost to you.

This is an independent guide. Paperclip Hosting is not affiliated with the official Paperclip project. Guide steps are based on real deployments and are subject to change as the software evolves.