# How to Connect n8n to MySQL

- Tool: n8n
- Difficulty: Beginner
- Time required: 15-20 minutes
- Compatibility: n8n 1.0+ (self-hosted and Cloud)
- Last updated: March 2026

## 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.

## Before you start

- 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 }}.

```
-- Example SELECT query in the MySQL node
SELECT id, email, created_at
FROM users
WHERE status = 'active'
ORDER BY created_at DESC
LIMIT 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.

```
-- Query with parameterized values (in the MySQL node Query field)
SELECT * FROM orders
WHERE customer_email = ?
AND status = ?
AND created_at > ?;

-- Query Parameters (in the node's Query Parameters field, as expressions):
-- Parameter 1: {{ $json.email }}
-- Parameter 2: {{ $json.status }}
-- 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.

```
-- Single row INSERT with parameters
INSERT INTO orders (customer_email, product_id, quantity, total)
VALUES (?, ?, ?, ?);

-- Query Parameters:
-- {{ $json.email }}
-- {{ $json.product_id }}
-- {{ $json.quantity }}
-- {{ $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 code example

File: `mysql-sync-workflow.js`

```javascript
// Code node: Transform and validate data before MySQL insert
// Place between a data source node and the MySQL node

const items = $input.all();
const validItems = [];
const invalidItems = [];

for (const item of items) {
  const data = item.json;

  // Validate required fields
  if (!data.email || !data.email.includes('@')) {
    invalidItems.push({
      json: {
        error: 'Invalid or missing email',
        original: data
      }
    });
    continue;
  }

  if (!data.product_id || typeof data.product_id !== 'number') {
    invalidItems.push({
      json: {
        error: 'Invalid or missing product_id',
        original: data
      }
    });
    continue;
  }

  // Sanitize and transform
  validItems.push({
    json: {
      email: data.email.trim().toLowerCase(),
      product_id: parseInt(data.product_id, 10),
      quantity: Math.max(1, parseInt(data.quantity || 1, 10)),
      total: parseFloat(data.total || 0).toFixed(2),
      created_at: new Date().toISOString().slice(0, 19).replace('T', ' ')
    }
  });
}

// Output 0: valid items → MySQL insert
// Output 1: invalid items → error logging
if (invalidItems.length > 0) {
  return [validItems, invalidItems];
}
return [validItems];
```

## Common mistakes

- **Using localhost as the MySQL host when both n8n and MySQL run in separate Docker containers** — undefined Fix: 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.
- **Concatenating user input directly into SQL strings, creating SQL injection vulnerabilities** — undefined Fix: Use n8n's query parameters feature with ? placeholders. Never build SQL strings with expression interpolation.
- **Running SELECT * without LIMIT on large tables, causing n8n to run out of memory** — undefined Fix: Always include a LIMIT clause and select only the columns you need. Process large datasets in batches using pagination.
- **Not handling connection errors, causing the entire workflow to fail on a transient network issue** — undefined Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/n8n-tutorial/how-to-connect-n8n-to-mysql
© RapidDev — https://www.rapidevelopers.com/n8n-tutorial/how-to-connect-n8n-to-mysql
