Skip to main content
RapidDev - Software Development Agency
n8n-tutorial

How to Connect n8n to MySQL

To connect n8n to MySQL, add a MySQL node to your workflow, create a MySQL credential with the host, port, database name, username, and password, then configure the node to run SELECT, INSERT, UPDATE, or DELETE queries. n8n's MySQL node supports parameterized queries to prevent SQL injection and can return results as JSON items for downstream processing.

What you'll learn

  • How to create MySQL credentials in n8n
  • How to run SELECT, INSERT, UPDATE, and DELETE queries using the MySQL node
  • How to use parameterized queries to prevent SQL injection
  • How to handle query results in downstream nodes
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read15-20 minutesn8n 1.0+ (self-hosted and Cloud)March 2026RapidDev Engineering Team
TL;DR

To connect n8n to MySQL, add a MySQL node to your workflow, create a MySQL credential with the host, port, database name, username, and password, then configure the node to run SELECT, INSERT, UPDATE, or DELETE queries. n8n's MySQL node supports parameterized queries to prevent SQL injection and can return results as JSON items for downstream processing.

Connecting n8n to MySQL for Database Queries and Automation

MySQL remains one of the most widely used relational databases, and connecting it to n8n lets you automate database operations like syncing records, generating reports, and triggering workflows from data changes. This tutorial shows you how to set up the connection, run queries, and handle results in your n8n workflows.

Prerequisites

  • A running n8n instance (self-hosted or Cloud)
  • A MySQL database accessible from the n8n server (network/firewall rules configured)
  • MySQL user credentials with appropriate permissions
  • Basic knowledge of SQL queries

Step-by-step guide

1

Create MySQL credentials in n8n

Open the n8n editor, go to Credentials in the left sidebar, and click Add Credential. Search for MySQL and select it. Fill in the connection details: Host (the MySQL server hostname or IP address), Port (default 3306), Database (the database name), User, and Password. If your MySQL server requires SSL, enable the SSL toggle and provide the certificate files. Click Test to verify the connection, then save the credential.

Expected result: The Test button shows a success message confirming n8n can connect to your MySQL database.

2

Add a MySQL node and run a SELECT query

Add a MySQL node to your workflow. In the node settings, select your MySQL credential from the Credential dropdown. Set the Operation to Execute Query. Write a SELECT query in the Query field. Each row from the result set becomes a separate n8n item, with column values accessible as JSON properties. You can reference these values in downstream nodes using expressions like {{ $json.column_name }}.

typescript
1-- Example SELECT query in the MySQL node
2SELECT id, email, created_at
3FROM users
4WHERE status = 'active'
5ORDER BY created_at DESC
6LIMIT 100;

Expected result: The MySQL node output shows one item per database row, with each column as a JSON property.

3

Use parameterized queries to prevent SQL injection

When your query includes dynamic values from webhook data or previous nodes, never concatenate them directly into the SQL string. Use n8n's query parameters feature instead. In the MySQL node, enable the Query Parameters option and pass values as an array. Use ? placeholders in your SQL query where dynamic values should go. n8n passes these values safely to MySQL, preventing SQL injection attacks.

typescript
1-- Query with parameterized values (in the MySQL node Query field)
2SELECT * FROM orders
3WHERE customer_email = ?
4AND status = ?
5AND created_at > ?;
6
7-- Query Parameters (in the node's Query Parameters field, as expressions):
8-- Parameter 1: {{ $json.email }}
9-- Parameter 2: {{ $json.status }}
10-- Parameter 3: {{ $json.start_date }}

Expected result: The query executes with safely escaped parameter values, returning only rows matching the dynamic criteria.

4

Insert data into MySQL from workflow results

To write data to MySQL, set the MySQL node's Operation to Execute Query and write an INSERT statement. Use query parameters for the values to insert. If you are processing multiple items from a previous node, the MySQL node runs the query once per item by default. For bulk inserts, use a Code node to build a single multi-row INSERT statement for better performance.

typescript
1-- Single row INSERT with parameters
2INSERT INTO orders (customer_email, product_id, quantity, total)
3VALUES (?, ?, ?, ?);
4
5-- Query Parameters:
6-- {{ $json.email }}
7-- {{ $json.product_id }}
8-- {{ $json.quantity }}
9-- {{ $json.total }}

Expected result: Rows are inserted into the MySQL table, and the node output confirms the number of affected rows.

5

Handle connection errors and timeouts

MySQL connections can fail due to network issues, incorrect credentials, or firewall rules. Configure error handling on the MySQL node by setting On Error to Continue (Using Error Output). This sends failed items to a separate error output branch where you can log the error, send notifications, or retry. Common errors include ECONNREFUSED (cannot reach the server), ER_ACCESS_DENIED_ERROR (wrong credentials), and ETIMEDOUT (firewall blocking the port).

Expected result: Errors are caught and routed to an error-handling branch instead of crashing the entire workflow.

Complete working example

mysql-sync-workflow.js
1// Code node: Transform and validate data before MySQL insert
2// Place between a data source node and the MySQL node
3
4const items = $input.all();
5const validItems = [];
6const invalidItems = [];
7
8for (const item of items) {
9 const data = item.json;
10
11 // Validate required fields
12 if (!data.email || !data.email.includes('@')) {
13 invalidItems.push({
14 json: {
15 error: 'Invalid or missing email',
16 original: data
17 }
18 });
19 continue;
20 }
21
22 if (!data.product_id || typeof data.product_id !== 'number') {
23 invalidItems.push({
24 json: {
25 error: 'Invalid or missing product_id',
26 original: data
27 }
28 });
29 continue;
30 }
31
32 // Sanitize and transform
33 validItems.push({
34 json: {
35 email: data.email.trim().toLowerCase(),
36 product_id: parseInt(data.product_id, 10),
37 quantity: Math.max(1, parseInt(data.quantity || 1, 10)),
38 total: parseFloat(data.total || 0).toFixed(2),
39 created_at: new Date().toISOString().slice(0, 19).replace('T', ' ')
40 }
41 });
42}
43
44// Output 0: valid items → MySQL insert
45// Output 1: invalid items → error logging
46if (invalidItems.length > 0) {
47 return [validItems, invalidItems];
48}
49return [validItems];

Common mistakes when connecting n8n to MySQL

Why it's a problem: Using localhost as the MySQL host when both n8n and MySQL run in separate Docker containers

How to avoid: Use the Docker service name (e.g., mysql or db) as the host, or use the Docker host IP. Inside a container, localhost refers to the container itself.

Why it's a problem: Concatenating user input directly into SQL strings, creating SQL injection vulnerabilities

How to avoid: Use n8n's query parameters feature with ? placeholders. Never build SQL strings with expression interpolation.

Why it's a problem: Running SELECT * without LIMIT on large tables, causing n8n to run out of memory

How to avoid: Always include a LIMIT clause and select only the columns you need. Process large datasets in batches using pagination.

Why it's a problem: Not handling connection errors, causing the entire workflow to fail on a transient network issue

How to avoid: Set On Error to Continue on the MySQL node and add an error-handling branch for retries or notifications.

Best practices

  • Always use parameterized queries with ? placeholders to prevent SQL injection attacks
  • Use LIMIT in SELECT queries to avoid loading excessive data into n8n memory
  • Create a dedicated MySQL user for n8n with only the permissions it needs (principle of least privilege)
  • Enable SSL for MySQL connections when the database is on a remote server
  • Use connection pooling on the MySQL server side to handle concurrent n8n executions
  • Validate and sanitize data in a Code node before inserting into MySQL
  • Set timeouts on the MySQL node to prevent long-running queries from blocking workflow execution
  • Test queries with small datasets first before running against production tables

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to connect my n8n workflow to a MySQL database running in a Docker container on the same server. Walk me through creating the credential, writing a parameterized SELECT query, and processing the results in downstream nodes.

n8n Prompt

Create a workflow with a Webhook trigger that receives a customer email, queries a MySQL database for that customer's recent orders using a parameterized query, and returns the results as JSON via a Respond to Webhook node.

Frequently asked questions

Does n8n support MySQL 8?

Yes, n8n supports MySQL 5.7 and MySQL 8.x. If you encounter authentication errors with MySQL 8, ensure the user uses the mysql_native_password authentication plugin, as some n8n versions may not support caching_sha2_password.

Can I use n8n with MariaDB?

Yes, MariaDB is wire-compatible with MySQL. Use the MySQL node and credential type in n8n to connect to MariaDB. The connection setup is identical.

How do I handle large result sets from MySQL?

Use LIMIT and OFFSET in your queries to paginate results. Process each page in a loop using the SplitInBatches node. Avoid loading more than 10,000 rows at once to prevent n8n memory issues.

Can I run stored procedures from n8n?

Yes, use the Execute Query operation and write CALL procedure_name(param1, param2) as the query. Result sets from stored procedures are returned as normal items.

Why do I get ECONNREFUSED when connecting to MySQL?

This means n8n cannot reach the MySQL server. Check that: the MySQL host and port are correct, the MySQL server is running, the firewall allows connections on port 3306, and if using Docker, both containers are on the same network.

Is the MySQL node deprecated in favor of PostgreSQL?

The MySQL node is not deprecated, but n8n recommends PostgreSQL as the database backend for n8n's own data. The MySQL node for querying external MySQL databases remains fully supported.

Can RapidDev help build MySQL-integrated n8n workflows?

Yes, RapidDev can design and implement n8n workflows that interact with MySQL databases, including complex queries, data synchronization, error handling, and performance optimization for high-volume operations.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.