n8n's PostgreSQL node lets you query, insert, update, and delete rows in a live Postgres database directly from a workflow — no backend script, no cron job, no separate service to maintain. Connect once with a credential, and any workflow can read customer records, write automation logs, sync data between systems, or trigger downstream actions the moment a row changes. For teams already running Postgres as their system of record, this one node quietly replaces a surprising amount of custom backend code.
Below is how the integration works, the query patterns that come up constantly, the mistakes that corrupt production data, and where this fits into a real n8n automation stack in 2026.
|
Key Takeaways 1. The PostgreSQL node supports four core operations — Execute Query, Insert, Update, and Delete — covering 90% of real-world automation needs without hand-writing raw SQL. 2. Connection pooling matters at scale. A workflow opening a new connection per execution will exhaust Postgres's connection limit under load. Use PgBouncer or n8n's built-in connection reuse. 3. Upserts (INSERT ... ON CONFLICT) are the pattern you'll use most. Syncing data from any external source into Postgres almost always needs conflict handling, not blind inserts. 4. Never trust user input in a raw query without parameterization. SQL injection is a one-line mistake with $Expression syntax, not a theoretical risk. 5. Postgres triggers + n8n webhooks let the database initiate workflows, not just receive from them — the pattern most people miss entirely. |
Most no-code automation platforms treat databases as an afterthought — a CSV export, a slow API wrapper, maybe a "database node" that only supports the four most basic operations. Postgres deserves better, and n8n gives it that.
Postgres is still the system of record for a huge share of production applications — CRMs, SaaS backends, internal tools, e-commerce platforms. If your automation needs to read live customer state, write structured logs, or keep two systems in sync, at some point you're touching Postgres directly. Doing that through a proper n8n workflow automation node instead of a bespoke script means you get retries, logging, and visual debugging for free.
The alternative — a Python or Node script running on a schedule — works, but now you're maintaining a deployment, a runtime, and error handling by hand. The n8n PostgreSQL node collapses all of that into a canvas you can see and edit in real time.
Where: n8n → Credentials → + New Credential → Postgres
You'll need five things from your database host (Supabase, RDS, Railway, self-hosted, whatever you're running):
1. Host — the connection address
2. Port — 5432 by default
3. Database name
4. User and Password
5. SSL mode — set to require for anything not on localhost; most managed Postgres hosts enforce this anyway
Once saved, the credential is reusable across every workflow in the instance. Worth doing once, carefully, rather than re-entering credentials per workflow — a single leaked entry is a bigger risk surface than one well-guarded one.
On n8n Cloud connecting to a database behind a firewall, you'll need to allowlist n8n's outbound IP ranges. Self-hosted n8n on the same network as your database skips this entirely.
Execute Query is the escape hatch — raw SQL, full control; use it when the built-in operations don't cover your case. Example: pulling a complex join across three tables for a reporting workflow.
|
SELECT c.id, c.name, o.total, o.created_at FROM customers c JOIN orders o ON o.customer_id = c.id WHERE o.created_at > NOW() - INTERVAL '7 days' ORDER BY o.created_at DESC; |
Insert writes new rows. Straightforward for append-only tables — automation logs, event tracking, form submissions.
Update modifies existing rows based on a match condition. Common pattern: update a contacts table's last_contacted column after an SMS workflow fires.
Delete removes rows matching a condition. Use sparingly and always test against a non-production database first — there's no undo button on a Delete node pointed at the wrong table.
For most real workloads, you'll live in Execute Query with parameterized statements rather than the simplified operations, because real logic usually needs conditional branches the basic operations can't express.
Almost every data-sync workflow needs to handle the case where a record might already exist. Blind inserts fail with a duplicate-key error the second time a workflow runs against the same source data. The fix is Postgres's native upsert syntax:
|
INSERT INTO leads (email, name, source, updated_at) VALUES ($1, $2, $3, NOW()) ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name, source = EXCLUDED.source, updated_at = NOW(); |
This single statement inserts a new lead if the email doesn't exist, or updates the row if it does. It's the backbone of any Customer Automation workflow that syncs leads from ad platforms, forms, or a CRM into your own database — no check-then-insert in two separate steps, which also closes a race-condition window a two-step check would leave open.
CRM sync into a reporting warehouse. A nightly n8n workflow queries the CRM's API, transforms the response, and upserts into a Postgres reporting table that Metabase or Superset reads from. No dbt pipeline needed for a small team — a schedule trigger plus a well-written upsert covers it.
Database-triggered notifications. Postgres supports LISTEN/NOTIFY and logical replication slots. Combine a lightweight relay (or Supabase's webhook-on-change feature) with an n8n webhook trigger, and a row update in Postgres can kick off a workflow — Slack alert, email, SMS — within seconds. This is the pattern most people miss: the database can initiate automation, not just receive from it.
AI agent with database context. A Custom AI Agent node in n8n can be given a PostgreSQL tool, letting the LLM query customer history, order status, or support tickets mid-conversation before responding. That's how a support chatbot answers "where's my order" with a real answer instead of a canned one.
Calling agent with live lookups. A Calling AI Agent handling inbound appointment calls can query Postgres in real time to check calendar availability before offering a slot, rather than working from a stale cached schedule.
Cross-platform contact sync. Client runs GHL for marketing and a custom Postgres-backed internal tool for fulfillment. An n8n workflow keeps both in sync bidirectionally — GHL webhook writes to Postgres, a scheduled query pushes changes back via its API. Two systems, one source of truth, no manual reconciliation.
Parameterize everything. Never concatenate user input directly into a SQL string. n8n's Postgres node supports $1, $2, $3 parameter placeholders specifically so you don't have to. The difference between this:
|
SELECT * FROM users WHERE email = '{{ $json.email }}' |
and this:
|
SELECT * FROM users WHERE email = $1 -- with $1 bound to {{ $json.email }} in the Query Parameters field |
is the difference between a safe query and a SQL injection vulnerability sitting in production. The first lets anyone submit ' OR '1'='1 as an email and pull every row. Always use bound parameters.
Use a read-only credential where possible. If a workflow only ever needs to read data, connect with a role that has SELECT only. A mistake in a later workflow then has nothing to break.
Never expose raw database errors to end users. Postgres error messages can leak schema details. Catch errors in n8n's error workflow and return a generic message externally while logging the real error internally.
1. Connection exhaustion under load. Postgres has a hard connection limit (often 100 by default). A high-volume webhook-triggered workflow opening a fresh connection per execution will hit that ceiling fast. Use PgBouncer in transaction mode in front of Postgres, or cap n8n's execution concurrency.
2. No transaction handling on multi-step writes. If a workflow inserts into two related tables and the second insert fails, you can end up with orphaned rows. Wrap related writes in an explicit BEGIN/COMMIT block via Execute Query when consistency matters.
3. Timezone mismatches. Postgres timestamp (without timezone) versus timestamptz causes silent bugs when n8n's workflow timezone doesn't match the column type. Standardize on timestamptz for anything automation touches.
4. Forgetting indexes on lookup columns. A workflow querying by email or external ID on an unindexed column slows down linearly as the table grows, then starts timing out. Index anything a workflow filters or joins on.
5. Testing against production. Every new workflow touching Postgres gets tested against a staging database or a disposable local instance first. A Delete node with a typo'd WHERE clause has ended more than one afternoon.
Simple read/write workflows against a well-indexed table are approachable for anyone comfortable with basic SQL. But once you're handling multi-table transactions, high-concurrency webhook triggers, or any workflow where data integrity failures cost real money, the calculus changes fast.
A properly built advanced n8n workflow involving database writes needs connection pooling, transaction boundaries, and error handling designed in from the start — not patched in after the first production incident. That's where a dedicated n8n expert pays for themselves inside the first month, because the cost of one corrupted table almost always beats the cost of doing the build properly.
Can n8n handle high-volume database writes?
Yes, with the right setup. Self-hosted n8n behind PgBouncer routinely handles thousands of writes per minute. The bottleneck is almost always Postgres connection limits, not n8n itself.
Does n8n support Postgres logical replication or CDC?
Not natively as a trigger type, but you can bridge it. Debezium publishes change events to a queue (Kafka, RabbitMQ), and n8n consumes from there via a webhook or queue-trigger node. For simpler cases, Supabase's realtime feature or a polling workflow covers most needs.
Is the PostgreSQL node the same as using Supabase's node?
Similar under the hood — Supabase is Postgres — but the dedicated Supabase node adds Supabase-specific features (auth, storage, realtime) on top of raw SQL access. On vanilla Postgres, RDS, or self-hosted, use the PostgreSQL node directly.
How do I avoid SQL injection in n8n workflows?
Always use parameterized queries with the Query Parameters field rather than string-interpolating user input into the SQL text. True whether the input comes from a form, webhook, or another API.
What's the fastest way to get expert help with this?
Get n8n Expert Service — a 30-minute audit of your current database automation and where it's exposed.
|
Ready to Connect Your Database to Real Automation? A PostgreSQL integration done right turns your database from a passive system of record into an active participant in your automation — syncing data, triggering workflows, feeding context to AI agents in real time. Done wrong, it's a production incident waiting to happen. We build production-grade Automation for teams running Postgres as their backbone — connection pooling, transaction safety, and monitoring included, not bolted on after the fact. 👉 Talk to our n8n expert service — free 30-minute audit of your database workflows, no pitch attached. |