2026-06-08

n8n Database Automation Guide: PostgreSQL, MySQL & Supabase Workflows

Connect n8n to PostgreSQL, MySQL, and Supabase for automated database operations. Sync data, run scheduled queries, build database triggers, and automate backups — all without writing cron jobs.

n8n Database Automation Guide: PostgreSQL, MySQL & Supabase

n8n can do more than connect SaaS apps — it's a powerful database automation engine. With native PostgreSQL, MySQL, and Supabase nodes, you can run queries on schedules, react to database changes, sync data between systems, and automate database maintenance.

This guide covers production patterns for database automation with n8n.

Why Automate Database Operations with n8n?

Traditional approach:

  • Write a Python/Node script
  • Set up a cron job
  • Handle errors, retries, and logging manually
  • Deploy and monitor the script
  • Repeat for every new automation

n8n approach:

  • Drag a database node onto the canvas
  • Write your SQL query
  • Connect to the next step
  • Deploy once, monitor everything in one dashboard

That's not laziness — that's leverage. Every hour you spend writing boilerplate cron scripts is an hour not spent on your product.

Setting Up Database Connections in n8n

PostgreSQL

1. Add a PostgreSQL node to your workflow
2. Configure credentials:
   - Host: your-db-host.com
   - Port: 5432
   - Database: your_database
   - User: your_user
   - Password: your_password
   - SSL: Enable for production
3. Test the connection

Important: Always use environment variables or n8n's credential store — never hardcode passwords in workflow JSON.

Supabase (PostgreSQL)

Supabase uses PostgreSQL under the hood, so you have two options:

  1. Supabase node (native) — simpler, uses Supabase client library
  2. PostgreSQL node — direct connection, full SQL power

For complex queries, use the PostgreSQL node with your Supabase connection string (found in Supabase Dashboard → Settings → Database → Connection string).

MySQL

1. Add a MySQL node
2. Configure credentials:
   - Host: your-db-host.com
   - Port: 3306
   - Database: your_database
   - User: your_user
   - Password: your_password
3. Test with a simple SELECT 1

Pattern 1: Scheduled Data Sync (ETL)

Use case: Sync your production database to a data warehouse or analytics DB every night.

[Cron: Daily 2 AM] → [PostgreSQL: SELECT * FROM orders WHERE created_at > yesterday]
  → [Transform: map columns, clean data]
    → [MySQL Analytics DB: INSERT INTO orders_archive]
      → [Slack notification: "Synced 1,247 orders"]

Key details:

  • Use incremental syncs (WHERE created_at > last_sync) — never SELECT * on large tables
  • Add a "last_sync_timestamp" table to track what's been synced
  • Batch inserts: INSERT INTO ... VALUES (...), (...), (...) for performance
  • Set reasonable timeouts — database queries can run long on large datasets

Pattern 2: Database Webhook Triggers

Use case: When a new row is inserted into a table, trigger an automation.

n8n doesn't have a "database trigger" node, but you have two options:

Option A: Polling (Simpler)

[Cron: Every 5 minutes] → [PostgreSQL: SELECT * FROM events WHERE processed = false LIMIT 100]
  → [For each row: process the event]
    → [UPDATE events SET processed = true WHERE id = {{ $json.id }}]

Option B: Supabase Database Webhooks (Recommended)

[Supabase Database Webhook: INSERT on events table] → [n8n Webhook node receives payload]
  → [Process event]
    → [Send Slack notification / call API / etc.]

Option B is real-time and doesn't waste resources polling. Use it whenever possible.

Pattern 3: Automated Backups

Use case: Daily database dumps stored to cloud storage with retention policy.

[Cron: Daily 3 AM] → [Execute Command node: pg_dump your_database > backup.sql]
  → [Compress: gzip backup.sql]
    → [Google Drive / S3: Upload backup-2026-06-08.sql.gz]
      → [Slack: "Backup complete: 47MB"]
      → [Cleanup: Delete backups older than 30 days]

Production hardening:

  • Test your backups regularly (automated restore test on staging)
  • Encrypt backups before uploading to cloud storage
  • Monitor backup size changes (sudden drops = likely failure)
  • Alert if backup hasn't run in 24 hours

Pattern 4: Data Cleanup and Maintenance

Use case: Archive old records, clean up stale data, run VACUUM.

[Cron: Weekly Sunday 4 AM] → [PostgreSQL: 
  BEGIN;
    -- Archive orders older than 90 days
    INSERT INTO orders_archive SELECT * FROM orders WHERE created_at < NOW() - INTERVAL '90 days';
    DELETE FROM orders WHERE created_at < NOW() - INTERVAL '90 days';
    -- Remove unverified users older than 30 days
    DELETE FROM users WHERE email_verified = false AND created_at < NOW() - INTERVAL '30 days';
    -- Clean up expired sessions
    DELETE FROM sessions WHERE expires_at < NOW();
  COMMIT;
]
  → [PostgreSQL: VACUUM ANALYZE orders;]
    → [Slack: "DB maintenance complete: archived 2,341 orders, removed 89 stale users"]

Safety first:

  • Always wrap destructive operations in BEGIN/COMMIT transactions
  • Test on a staging database first
  • Add a "dry run" mode that logs what WOULD be deleted without actually deleting
  • Keep archive tables — don't just DELETE, INSERT INTO archive first

Pattern 5: Cross-Database Data Sync

Use case: Keep your local development database in sync with production (anonymized).

[Cron: Daily 6 AM] → [PostgreSQL (Prod): SELECT * FROM users]
  → [Transform: anonymize emails, scrub phone numbers, replace names with fake data]
    → [MySQL (Dev): REPLACE INTO users (...)]
      → [Slack: "Dev DB synced with anonymized production data"]

Pattern 6: Query Result Distribution

Use case: Run a weekly sales report and email it to stakeholders.

[Cron: Every Monday 8 AM] → [PostgreSQL: 
  SELECT 
    date_trunc('week', created_at) as week,
    COUNT(*) as orders,
    SUM(amount) as revenue,
    AVG(amount) as avg_order_value
  FROM orders 
  WHERE created_at > NOW() - INTERVAL '4 weeks'
  GROUP BY week 
  ORDER BY week DESC;
]
  → [Convert to CSV or format as HTML table]
    → [SendGrid: Email "Weekly Sales Report" to finance@company.com with attachment]

Security Best Practices

1. Use Read-Only Database Users for Queries

Don't connect n8n with your admin/superuser credentials. Create a dedicated user with minimum required permissions:

-- PostgreSQL: Read-only user for SELECT queries
CREATE USER n8n_reader WITH PASSWORD 'strong-password-here';
GRANT CONNECT ON DATABASE your_db TO n8n_reader;
GRANT USAGE ON SCHEMA public TO n8n_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO n8n_reader;

-- For workflows that need INSERT/UPDATE, create a separate user:
CREATE USER n8n_writer WITH PASSWORD 'different-strong-password';
GRANT SELECT, INSERT, UPDATE ON orders, events, users TO n8n_writer;

2. Never Expose Database Credentials in Workflow JSON

n8n's credential system encrypts credentials at rest. Always use credentials — never paste connection strings into the Execute SQL field.

3. Use SSL/TLS Connections

In production, always enable SSL for database connections. n8n's PostgreSQL and MySQL nodes have SSL toggle switches. Turn them on.

4. Network-Layer Security

If n8n and your database are in the same VPC, restrict database access to n8n's IP only via security groups or firewall rules. Don't expose your database to the public internet.

5. Query Parameterization

Never concatenate user input into SQL queries. Use n8n's expression syntax:

-- ❌ Dangerous: SQL injection risk
SELECT * FROM users WHERE email = '{{ $json.email }}'

-- ✅ Use parameterized queries or sanitize inputs
SELECT * FROM users WHERE email = {{ $json.email | quote }}

Performance Tips

1. Limit result sets. Never SELECT * FROM huge_table without LIMIT. n8n loads results into memory.

2. Use database-side aggregation. Let PostgreSQL/MySQL do the heavy math — don't pull 100,000 rows into n8n for a simple COUNT.

3. Batch operations. For inserts/updates, batch them in groups of 100-1000 rows. Individual INSERT per row is extremely slow.

4. Connection pooling. In n8n settings, configure connection pool size. Too many concurrent connections can overwhelm your database.

5. Index your query columns. If a scheduled query runs every 5 minutes and takes 30 seconds, you need an index on the WHERE clause columns.

Monitoring Automated Database Workflows

Set up these alerts:

  • Execution time degradation — if a query that normally takes 2 seconds starts taking 30 seconds, investigate before it fails
  • Zero rows returned — if a sync that normally returns thousands returns zero, the source may be broken
  • Failed connection attempts — database credentials expire or IPs get firewalled
  • Disk space on the n8n server — backups and temp files can fill up quickly

Getting Started: Your First Database Automation

Here's a simple one to try today:

[Cron: Every 6 hours] → [PostgreSQL: 
  SELECT COUNT(*) as user_count, 
         COUNT(CASE WHEN created_at > NOW() - INTERVAL '24 hours' THEN 1 END) as new_today
  FROM users;
]
  → [IF new_today > 50: Slack alert "🔥 High signup day! 50+ new users"]
  → [INSERT INTO metrics_daily (metric, value, recorded_at) VALUES ('user_count', {{ $json.user_count }}, NOW())]

That's a real-time growth monitor in 3 nodes.

Browse database automation templates →`

Ready to automate?

Browse 25+ production-ready n8n templates. Import, configure, and run — all in under 10 minutes.

Browse Templates