MySQL powers WordPress, Shopify storefronts, Laravel apps, and countless internal business tools. The n8n MySQL node lets you read from and write to any MySQL (or MariaDB) database inside your automation workflows, without writing connection boilerplate.
This guide covers credential setup, every operation the node supports, the gotchas that trip people up, and a free workflow JSON you can import today.
What the n8n MySQL Node Can Do
| Operation | What it does |
|---|---|
| Execute Query | Run any raw SQL — SELECT, INSERT, UPDATE, DELETE, or stored procedures |
| Insert | Insert one or more rows from workflow data |
| Update | Update rows matching a WHERE column value |
| Delete | Delete rows matching a WHERE column value |
| Execute Stored Procedure | Call a named stored procedure with parameters |
For most use cases, Execute Query is the most flexible option. The dedicated Insert/Update/Delete operations are convenient for simple single-table writes, but Execute Query handles joins, transactions, and complex WHERE clauses that the simplified operations cannot.
Credential Setup
In n8n, go to Credentials → New → MySQL. You need:
-
Host — your database host (e.g.,
db.example.comor127.0.0.1) - Database — the database name
- User and Password
- Port — default 3306
- SSL — toggle on for cloud databases (required for PlanetScale, Railway, AWS RDS, Google Cloud SQL)
Common gotcha: Cloud MySQL providers require SSL. Toggle SSL on and set Verify server certificate based on whether you have a CA cert. If you get a connection error on a cloud database, SSL is almost always the first thing to check.
MariaDB: The MySQL node works with MariaDB too — use the same credential type. Newer MariaDB versions may need allowPublicKeyRetrieval: true if you see authentication plugin errors.
Execute Query — Raw SQL
The most powerful operation. Use it for anything the simplified operations cannot handle.
Simple SELECT:
SELECT id, email, created_at FROM users WHERE status = 'active' LIMIT 100;
Parameterized query (recommended — prevents SQL injection):
SELECT * FROM orders WHERE customer_id = ? AND status = ?
With Query Parameters set to: ={{ $json.customer_id }},{{ $json.status }}
Always use ? placeholders and pass values through Query Parameters rather than interpolating them directly into the SQL string. This prevents SQL injection and handles escaping automatically.
INSERT with returning the new ID:
INSERT INTO leads (email, source, created_at) VALUES (?, ?, NOW())
The node returns { affectedRows: 1, insertId: 42 } — use {{ $json.insertId }} in the next node.
UPDATE multiple columns:
UPDATE contacts SET last_seen = NOW(), status = ? WHERE id = ?
Insert Operation
The Insert operation lets you map workflow fields to table columns without writing SQL.
- Set Operation to Insert
- Set Table to your target table name
- Under Columns, map each column to a workflow expression:
email → {{ $json.email }}
This is the fastest path for simple single-table inserts. For batch inserts from a list, combine with Split In Batches upstream to avoid hitting MySQL's max_allowed_packet limit.
Update Operation
Update finds rows by a key column and updates the rest.
- Set Operation to Update
- Set Table and the Update Key (the column used in the WHERE clause, e.g.,
id) - Map the columns to update
The Update Key value comes from {{ $json.id }} — n8n constructs UPDATE table SET col=val WHERE key_col=key_val for you.
Common Patterns
Webhook → INSERT → respond
Receive a form or API payload, insert it into MySQL, return a confirmation.
- Webhook node receives the POST
-
MySQL node inserts the data (
INSERT INTO leads (email, name) VALUES (?, ?)) -
Respond to Webhook returns
{ "success": true, "id": "{{ $json.insertId }}" }
Daily report: SELECT → Google Sheets
- Cron trigger fires daily
-
MySQL runs
SELECT * FROM orders WHERE DATE(created_at) = CURDATE() - Google Sheets node appends the rows to a daily log sheet
External API → MySQL upsert
- HTTP Request fetches records from an external API
- MySQL executes an INSERT ... ON DUPLICATE KEY UPDATE:
INSERT INTO products (sku, name, price) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE name=VALUES(name), price=VALUES(price)
Gotchas Table
| Symptom | Root cause | Fix |
|---|---|---|
ECONNREFUSED |
Host unreachable or wrong port | Check host, port 3306, firewall/security group rules |
ER_ACCESS_DENIED_ERROR |
Wrong user/password or insufficient privileges | Grant SELECT, INSERT, UPDATE, DELETE on the specific database |
| SSL connection error | Cloud DB requires SSL, toggle is off | Enable SSL in credentials; set Verify server certificate appropriately |
ER_PARSE_ERROR |
SQL syntax error | Test query in a MySQL client first; backtick reserved-word column names |
affectedRows: 0 on UPDATE |
WHERE clause matched nothing | Log the key value before the query; verify the record exists |
| Timeout on large SELECTs | Returning too many rows | Add LIMIT; paginate with OFFSET; or use Split In Batches |
insertId: 0 on INSERT |
Table has no AUTO_INCREMENT primary key | Expected — insertId is only set when an auto-increment column exists |
Free Workflow JSON — Webhook → MySQL Lead Capture
This workflow receives a form submission via webhook, inserts the lead into a MySQL table, and responds with the new record ID.
Required table:
CREATE TABLE leads (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
name VARCHAR(255),
source VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Drop a comment below and I'll share the full workflow JSON — just tell me which MySQL provider you're using (PlanetScale, Railway, RDS, or self-hosted) and I'll include the right SSL config.
Workflow Starter Pack ($29)
If you want pre-built, production-ready workflows with error handling, retry logic, and Slack alerting built in, the n8n Workflow Starter Pack includes a complete MySQL lead capture and sync workflow alongside 2 other production workflows.
Every workflow is documented, tested, and imports in under 2 minutes.
What do you use MySQL for in your n8n workflows? SELECT queries for reporting, writes from webhooks, or keeping a database in sync with an external API? Let me know in the comments.
Top comments (1)
Quick setup tip for MySQL connections in n8n 🛢️
If you're getting "Connection refused" on port 3306, the most common culprit is the MySQL user not being granted remote access. Run this in your MySQL shell:
Also: if you're running n8n in Docker and MySQL on the host, use
host.docker.internalinstead oflocalhost— caught me out the first time.Which MySQL operation do you use most in your n8n workflows — reads, writes, or upserts?****