n8n's default self-hosted database is SQLite, a single-file database that works fine for evaluation and light personal use but becomes a genuine liability the moment you're running production workflows with real concurrent execution volume. SQLite's file-level locking model means concurrent writes queue up rather than running in parallel, exactly the pattern a business running dozens of simultaneous workflow executions will hit. PostgreSQL is the production-grade alternative n8n officially supports, and this guide covers the real setup, not just the one-line environment variable most tutorials stop at.
Why SQLite Breaks Down in Production
| Failure mode | Why it happens | When you'll notice |
|---|---|---|
| Execution queue backups | SQLite serializes writes; concurrent workflow executions queue rather than running in parallel | Multiple workflows triggering simultaneously, common in any real business with several active automations |
| Database file corruption risk | A single-file database is more vulnerable to corruption from an unclean shutdown | Server restarts, crashes, or resource exhaustion events |
| No real backup strategy | File-based backups require stopping n8n or accepting inconsistent snapshots | The exact moment you need a reliable backup, after an incident |
| Poor performance at scale | Query performance degrades as the execution history table grows without proper indexing options | Months into production use, as historical execution data accumulates |
PostgreSQL Setup: The Real Environment Variables
Configuring n8n to use PostgreSQL instead of SQLite requires setting the following environment variables before n8n's first startup (changing database backend after data exists in SQLite requires a proper migration, not just a variable change):
For a Docker Compose deployment specifically, these variables are set in the n8n service's environment block, with the PostgreSQL service defined as a separate container in the same Compose file, connected via Docker's internal networking rather than an external database connection string, unless you're deliberately using a managed database service.
What the Schema Actually Contains
n8n manages its own schema migrations automatically on startup, you don't hand-write the schema, but understanding what it contains matters for anyone managing the database directly (for backups, monitoring, or troubleshooting). The core tables include: `workflow_entity` (workflow definitions), `execution_entity` (execution history and status), `credentials_entity` (encrypted credential storage), `webhook_entity` (registered webhook endpoints), and `settings` (instance-level configuration). The execution history table is typically the fastest-growing and the one most worth actively managing (via n8n's built-in execution data pruning settings) to prevent unbounded database growth in a high-volume production instance.
Managed PostgreSQL vs Self-Managed
| Option | Best fit | Tradeoff |
|---|---|---|
| Self-managed PostgreSQL (same server as n8n, or a separate VPS) | Lowest infrastructure cost, full control | You own backup, patching, and failover entirely |
| Managed PostgreSQL (DigitalOcean Managed Databases, AWS RDS, similar) | Teams wanting reliability without database administration overhead | Moderate additional cost, but includes automated backups and easier failover |
For most PURIST client deployments past the smallest scale, a managed PostgreSQL instance is worth the incremental cost specifically because database administration is exactly the kind of specialized, easy-to-get-wrong work that benefits from a managed service, freeing engineering time for the actual automation logic rather than database operations.
Migrating Existing Data from SQLite
n8n does not provide a fully automated SQLite-to-PostgreSQL migration tool as a one-click feature; the reliable path is exporting existing workflows via the API or UI (as JSON), standing up a fresh PostgreSQL-backed instance, and re-importing the workflow definitions, accepting that execution history typically does not migrate cleanly and is usually treated as an acceptable loss for a database backend migration, rather than attempting a risky in-place data migration.
Sources & Further Reading
Configuration details reflect n8n's official self-hosting documentation as of publication; verify current environment variable names and defaults against your specific n8n version. See n8n's official database configuration documentation for the authoritative reference. For the broader self-hosted infrastructure decision this fits into, see n8n self-hosted vs cloud: the complete decision guide, and for the general Docker deployment pattern, see n8n Docker: production deployment guide.
Performance Tuning Beyond the Default Configuration
Once running on PostgreSQL, a few configuration adjustments meaningfully improve performance at real production volume beyond n8n's out-of-box defaults: enabling connection pooling (via PgBouncer or similar) prevents connection exhaustion under high concurrent execution load, a genuine risk once you're running dozens of simultaneous workflow executions each opening their own database connection. Setting an appropriate `execution_data_pruning` interval (n8n's built-in setting for automatically deleting old execution records) keeps the execution history table from growing unbounded, which otherwise degrades query performance over months of accumulated production use.
Monitoring Database Health in Production
| Metric to watch | Why it matters | Warning sign |
|---|---|---|
| Connection count | Approaching your PostgreSQL max_connections limit causes new executions to fail | Consistently near the configured maximum during normal operation |
| Table size growth (execution_entity specifically) | Unbounded growth without pruning degrades query performance | Table size growing faster than your pruning interval would predict |
| Query latency on workflow/execution lookups | Slow queries here directly slow down the n8n UI and API | Noticeably slower workflow list or execution history loading over time |
| Disk space on the database volume | Running out of disk space causes writes to fail entirely | Consistent upward trend approaching allocated volume size |
Disaster Recovery: Testing Your Backup, Not Just Taking One
A backup that has never been restored is an assumption, not a verified safety net. Periodically test restoring your PostgreSQL backup to a separate, non-production instance and confirm n8n starts correctly against the restored data, including verifying that the `N8N_ENCRYPTION_KEY` used matches (a mismatched key after restoration renders all stored credentials unreadable even with a technically successful database restore, exactly the failure mode covered in our Docker production deployment guide). This test should happen on a defined schedule, not only after an actual incident reveals a backup gap.
Scaling PostgreSQL Beyond a Single Server
For n8n deployments running genuinely high execution volume, a dedicated, appropriately-sized PostgreSQL instance (separate from the n8n application server) with read replicas for reporting queries becomes worth considering, though this level of scaling is well beyond what the large majority of SMB and mid-market automation deployments actually need. Most PURIST client deployments never require scaling past a single, properly-configured PostgreSQL instance colocated with or adjacent to the n8n application server.
What to Verify Before Going Live
- Have we actually tested a full backup restoration, not just confirmed backups are being created?
- Is our `N8N_ENCRYPTION_KEY` backed up separately and securely, not just bundled with the database backup?
- Have we set an appropriate execution data pruning interval matching our real operational and compliance needs?
- Does our PostgreSQL instance have connection pooling configured if we're running meaningful concurrent execution volume?
Sources & Further Reading
Configuration details reflect n8n's official self-hosting and database documentation as of publication; verify current settings against your specific n8n version. See n8n's official documentation for the authoritative reference.
For related reading, see n8n Docker: the production deployment guide for the full containerized deployment this database configuration fits into, and n8n Cloud vs self-hosted: the real decision framework for the broader hosting decision.
Common Mistakes When Setting Up PostgreSQL for n8n
Skipping the encryption key backup because the database backup feels sufficient. This is the single most damaging and most common oversight in self-hosted n8n backup strategy; a database backup without the matching encryption key still results in every stored credential becoming unrecoverable after a restore.
Never testing a real restore until an actual incident forces it. A backup that has never been restored is unverified; schedule periodic restore tests to a non-production instance rather than discovering a gap during a real emergency.
Ignoring execution history growth until it visibly slows down the instance. Set a sensible pruning interval from the start rather than waiting for degraded performance to force a reactive cleanup under pressure.
A Realistic Scenario: A Near-Miss Recovery
A business running self-hosted n8n on a single VPS experienced a hardware failure requiring a full server rebuild. Their PostgreSQL backups restored cleanly, but the encryption key, stored only as a file on the failed server itself with no separate backup, was gone. Every one of their roughly 40 stored credentials had to be manually re-entered across all their production workflows, a multi-day recovery effort that a five-minute separate encryption-key backup would have entirely avoided. This is now the first item PURIST checks in any self-hosted n8n infrastructure audit, precisely because of how common and how avoidable this specific failure mode is.
The 3-Year View: Database Needs as Automation Volume Grows
| Year | Typical database need | What changes |
|---|---|---|
| Year 1 | Single PostgreSQL instance, default configuration | Sufficient for most starting automation volume |
| Year 2 | Connection pooling and tuned pruning intervals become worth implementing | Execution volume and history size both grow meaningfully |
| Year 3 | Dedicated database resource sizing, possibly separate from the application server | Only for genuinely high-volume deployments; most businesses never need to go this far |
The overwhelming majority of PURIST client deployments never progress past the year-two stage of this table, a single, properly-configured and tuned PostgreSQL instance colocated with the n8n application comfortably serves real production automation needs for the vast majority of SMB and mid-market businesses indefinitely.
Advanced Configuration for High-Reliability Deployments
For businesses running genuinely mission-critical automation on self-hosted PostgreSQL, several additional configuration layers beyond the standard setup covered earlier in this guide are worth considering, though they add real operational complexity and aren't necessary for the majority of deployments.
| Configuration | What it adds | When it's worth the added complexity |
|---|---|---|
| Streaming replication to a standby replica | A near-real-time hot standby database ready to take over if the primary fails | Automation genuinely critical enough that even brief downtime has meaningful business cost |
| Automated failover tooling (e.g., Patroni) | Automatic promotion of a replica to primary without manual intervention | High-availability requirements beyond what manual failover response time can satisfy |
| Point-in-time recovery configuration | Ability to restore the database to any specific moment, not just the last full backup | Compliance or forensic requirements needing granular historical recovery capability |
The large majority of PURIST client deployments never need this tier of configuration, a well-configured single instance with tested backups (covered earlier in this guide) satisfies the reliability bar for most business automation. This advanced tier belongs specifically to businesses where automation downtime has a direct, quantifiable, and significant cost, worth explicitly confirming that's genuinely your situation before investing in the added operational complexity these patterns require.
Troubleshooting Common PostgreSQL Connection Issues
The most frequently encountered production issue after a successful initial setup is connection exhaustion, n8n and any monitoring or API-driven tooling querying the database can collectively exceed PostgreSQL's default `max_connections` setting under real concurrent load. The fix is twofold: implementing connection pooling (mentioned earlier in this guide) to reduce the actual number of direct database connections needed, and explicitly reviewing and raising the `max_connections` setting itself if your genuine concurrency needs exceed PostgreSQL's conservative default. Diagnosing this issue typically shows up as intermittent, hard-to-reproduce workflow execution failures specifically under higher load, exactly the kind of failure the health monitoring layer covered in our error handling guide is designed to catch and alert on before it becomes a recurring, unexplained reliability complaint.
Frequently Asked Questions
At what point do I actually need to switch from SQLite to PostgreSQL?
Once you have more than a handful of active workflows with any meaningful concurrent execution likelihood, or once you're running n8n as genuine business infrastructure rather than personal/evaluation use, migrate proactively rather than waiting for a concurrency-related failure to force the issue.
Does PostgreSQL make n8n itself faster, or just more reliable under concurrency?
Primarily the latter; for low-volume, non-concurrent use, SQLite and PostgreSQL perform similarly. PostgreSQL's advantage is specifically in handling concurrent writes and scaling execution history query performance as data grows.
Can I run n8n and PostgreSQL on the same small VPS?
Yes, for small-to-moderate automation volume, a single reasonably-sized VPS running both n8n and PostgreSQL (via Docker Compose) is a common and cost-effective setup; separate the two onto different infrastructure once either resource contention or reliability requirements justify the added complexity.
How often should execution history be pruned in production?
n8n's built-in data pruning settings (configurable retention period) should be set based on your actual need to review historical executions, commonly 2-4 weeks for routine debugging purposes, longer if compliance or audit requirements demand extended retention.
Is DigitalOcean specifically a good host for this setup?
DigitalOcean's Managed Databases product for PostgreSQL, paired with a Droplet running n8n, is a commonly used and reasonably priced combination for this exact setup; any cloud provider offering managed PostgreSQL works equivalently, the choice is largely about existing infrastructure relationships and regional availability.
Can I use MySQL instead of PostgreSQL for self-hosted n8n?
n8n officially supports PostgreSQL as its recommended production database; verify current database support in n8n's documentation before assuming MySQL compatibility, as officially supported options can be narrower than the underlying ORM's theoretical compatibility might suggest.
How much disk space should I provision for the PostgreSQL volume?
This depends heavily on execution volume and your pruning interval; a reasonable starting allocation for moderate SMB automation volume is 20-50GB with room to grow, monitored and expanded proactively rather than waiting for a disk-full failure.
Does switching to PostgreSQL improve n8n's UI responsiveness, or just backend reliability?
Primarily backend reliability and concurrency handling; UI responsiveness is more affected by execution history size and pruning configuration than by the database engine choice itself, though a well-configured PostgreSQL instance with proper indexing handles large execution histories more gracefully than SQLite would at the same scale.
Does n8n support any database besides SQLite and PostgreSQL?
PostgreSQL is n8n's officially recommended and supported production database; always verify current officially supported options in n8n's documentation before assuming compatibility with any other database engine.
How do I know if my current instance is still running on SQLite without checking configuration files directly?
Check your environment variables for `DB_TYPE`; if it's unset or explicitly `sqlite`, you're on the default SQLite backend, and if you're running any meaningful production workflow volume, this guide's migration path is worth prioritizing.
Can I run PostgreSQL in a Docker container on the same host as n8n without a separate server?
Yes, this is the common pattern covered in our Docker production deployment guide, both services run as separate containers within the same Docker Compose stack on one host, a cost-effective setup for most SMB automation volume.
Does upgrading n8n versions ever require manual database schema changes?
n8n manages its own schema migrations automatically on startup when you upgrade versions; however, always back up your database before any version upgrade regardless, since an automatic migration still carries some inherent risk worth having a rollback path for.
Can I run n8n's PostgreSQL database on a serverless database platform?
Serverless PostgreSQL options exist and can work, but verify connection-handling behavior specifically, since some serverless database platforms have cold-start latency or connection-limit behaviors that interact differently with n8n's connection patterns than a traditional always-on PostgreSQL instance.
How do I know if my PostgreSQL instance is properly sized for my automation volume?
Monitor CPU, memory, and connection count under real production load over at least a few weeks; if any of these consistently run near their allocated limits during normal operation (not just occasional spikes), that's a clear signal to size up before performance degrades further.
Does n8n support connecting to an existing PostgreSQL database already used by other applications?
Technically possible using a dedicated schema within a shared database instance, but a dedicated PostgreSQL instance for n8n specifically is the more common and safer practice, avoiding resource contention and permission-scoping complexity with unrelated applications.
What's the simplest way to verify our current setup is actually production-ready?
Run through this guide's 'what to verify' checklist explicitly against your current instance, tested restore, backed-up encryption key, connection pooling if needed, rather than assuming production-readiness based on the instance simply running without errors day to day.
Does PostgreSQL version matter for n8n compatibility?
n8n documents its officially supported PostgreSQL version range; verify your target version falls within that supported range before deployment, since an unsupported version can cause subtle, hard-to-diagnose compatibility issues.
Can I use the same PostgreSQL instance for both a staging and production n8n environment?
Technically possible using separate databases within the same instance, but a fully separate PostgreSQL instance per environment is the safer practice, preventing any risk of staging activity affecting production data or performance.
Is it worth encrypting the PostgreSQL database itself at rest, beyond n8n's own credential encryption?
For businesses with elevated data sensitivity or specific compliance requirements, full-disk or database-level encryption at rest is a reasonable additional layer; for most standard business automation use cases, n8n's own credential-level encryption combined with standard server security practices is sufficient.
Is it necessary to hire a dedicated database administrator for this setup?
Not for most SMB-scale deployments; a competent DevOps-capable team member or a managed hosting relationship covers routine PostgreSQL administration needs without requiring a dedicated DBA role, which only becomes relevant at a scale most businesses reading this guide won't reach.
Does n8n plan to support additional database backends beyond PostgreSQL and SQLite in the future?
Check n8n's public roadmap or release notes for the most current information on supported database backends, since this is exactly the kind of platform capability that can expand over time beyond what's covered in this guide at publication.
To get a properly configured, production-grade PostgreSQL setup for your self-hosted n8n instance, book a free automation audit. We deploy and maintain exactly this infrastructure for clients running n8n at real production scale.
Tags
Purist Team
The PURIST editorial team covers automation, AI agents, and operations strategy for businesses scaling with n8n, Make, and Claude AI.