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
Create MySQL credentials in n8n
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.
Add a MySQL node and run a SELECT query
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 }}.
1-- Example SELECT query in the MySQL node2SELECT id, email, created_at3FROM users4WHERE status = 'active'5ORDER BY created_at DESC6LIMIT 100;Expected result: The MySQL node output shows one item per database row, with each column as a JSON property.
Use parameterized queries to prevent SQL injection
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.
1-- Query with parameterized values (in the MySQL node Query field)2SELECT * FROM orders3WHERE customer_email = ?4AND status = ?5AND created_at > ?;67-- 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.
Insert data into MySQL from workflow results
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.
1-- Single row INSERT with parameters2INSERT INTO orders (customer_email, product_id, quantity, total)3VALUES (?, ?, ?, ?);45-- 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.
Handle connection errors and timeouts
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
1// Code node: Transform and validate data before MySQL insert2// Place between a data source node and the MySQL node34const items = $input.all();5const validItems = [];6const invalidItems = [];78for (const item of items) {9 const data = item.json;1011 // Validate required fields12 if (!data.email || !data.email.includes('@')) {13 invalidItems.push({14 json: {15 error: 'Invalid or missing email',16 original: data17 }18 });19 continue;20 }2122 if (!data.product_id || typeof data.product_id !== 'number') {23 invalidItems.push({24 json: {25 error: 'Invalid or missing product_id',26 original: data27 }28 });29 continue;30 }3132 // Sanitize and transform33 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}4344// Output 0: valid items → MySQL insert45// Output 1: invalid items → error logging46if (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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation