MySQL
Datafly Signal writes first-party events into a MySQL table for high-performance relational storage with JSON column support and broad ecosystem compatibility.
Why route MySQL through Datafly Signal
- The data lands in infrastructure you own. Signal writes to your MySQL directly from your own deployment. Datafly operates no intermediary and never holds a copy of your event data.
- Client IP and user agent are recorded as event context. Both come from the original visitor request rather than from your server, so geography and device analysis done in the warehouse reflects the actual visitor.
- One consent decision governs every destination. MySQL is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.
Prerequisites
Before configuring MySQL in Signal, you need a MySQL server (self-hosted or managed), a database and table, and a user with INSERT privileges.
Set Up a MySQL Server
You have several options:
Option A: Managed MySQL
- Amazon RDS for MySQL — Create an RDS instance
- Azure Database for MySQL — Create an Azure MySQL server
- Google Cloud SQL for MySQL — Create a Cloud SQL instance
- PlanetScale, Aiven, or other managed providers
Option B: Self-Hosted MySQL
- Install MySQL using the official guide.
- Start the MySQL server.
- Ensure the server is accessible from your Signal infrastructure on port
3306.
Configure Network Access
Ensure your MySQL server accepts connections from Signal’s IP addresses:
- RDS: Configure the security group inbound rules.
- Azure: Add firewall rules in the Networking tab.
- Cloud SQL: Add authorised networks.
- Self-hosted: Configure the
bind-addressinmy.cnfand firewall rules.
Create a Database and Table
Connect to the MySQL server and create the target database and table:
CREATE DATABASE datafly_events;
USE datafly_events;
CREATE TABLE events (
event_id VARCHAR(64) NOT NULL PRIMARY KEY,
type VARCHAR(20),
event VARCHAR(256),
anonymous_id VARCHAR(64),
user_id VARCHAR(256),
timestamp DATETIME(3),
received_at DATETIME(3),
sent_at DATETIME(3),
context JSON,
properties JSON,
traits JSON,
source_id VARCHAR(64),
integration_id VARCHAR(64),
INDEX idx_timestamp (timestamp DESC),
INDEX idx_type_event (type, event)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;Using utf8mb4 character set ensures full Unicode support. The JSON column type allows flexible querying with MySQL’s JSON functions (e.g. JSON_EXTRACT, ->).
Create a User for Signal
CREATE USER 'datafly_signal'@'%' IDENTIFIED BY 'your_secure_password';
GRANT INSERT ON datafly_events.events TO 'datafly_signal'@'%';
FLUSH PRIVILEGES;Replace '%' with Signal’s specific IP address or CIDR range for tighter security. The % wildcard allows connection from any host.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
host | string | Yes | The MySQL server hostname. |
port | string | Yes | The MySQL server port. Defaults to 3306. |
database | string | Yes | The target database name. |
table_name | string | Yes | The target table name to insert rows into. |
username | string | Yes | The database username for authentication. |
password | secret | Yes | The database password for authentication. |
tls_mode | select | No | TLS mode: disabled, preferred, required, verify-ca, or verify-identity. Defaults to preferred. Also accepts the legacy use_tls boolean. |
Signal Setup
Quick Setup
- Navigate to Integrations in the sidebar.
- Open the Integration Library tab.
- Find MySQL or filter by Database.
- Click Install, select a variant if available, and fill in the required fields.
- Click Install Integration to create the integration with a ready-to-use default blueprint.
API Setup
curl -X POST http://localhost:8084/v1/admin/integration-catalog/mysql/install \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "MySQL",
"variant": "default",
"config": {
"host": "db.example.com",
"port": "3306",
"database": "datafly_events",
"table_name": "events",
"username": "datafly_signal",
"password": "your_secure_password",
"tls_mode": "required"
},
"delivery_mode": "server_side"
}'Schema
Signal writes the standard event envelope. The recommended table definition:
| Column | MySQL type | Notes |
|---|---|---|
event_id | VARCHAR(64) NOT NULL PRIMARY KEY | Unique per event. |
type | VARCHAR(20) | Event type. |
event | VARCHAR(256) | Event name (snake_case). |
anonymous_id | VARCHAR(64) | First-party visitor identifier. |
user_id | VARCHAR(256) | Logged-in user identifier (nullable). |
timestamp | DATETIME(3) | Client event time, millisecond precision. |
received_at | DATETIME(3) | Time Signal received the event. |
sent_at | DATETIME(3) | Time the row was delivered. |
context | JSON | Page, device, user agent, consent metadata. |
properties | JSON | Custom event properties. |
traits | JSON | User traits. |
source_id | VARCHAR(64) | Pipeline source identifier. |
integration_id | VARCHAR(64) | Signal integration identifier. |
Query JSON columns with JSON_EXTRACT() or the -> / ->> operators (MySQL 5.7+).
Consent
MySQL is a first-party destination under your control. The default blueprint forwards all events. Apply consent filtering via pipeline transforms or downstream views over context->'$.consent' if needed.
Testing
- Enable the integration in Signal and trigger a test event on your website.
- Connect to the MySQL server and query the target table:
SELECT * FROM datafly_events.events ORDER BY timestamp DESC LIMIT 10;- Verify that event rows are appearing with correct data.
- In Signal, check the Live Events view to confirm delivery status shows as successful.
Troubleshooting
| Problem | Solution |
|---|---|
| Events not appearing in the table | Verify the host, port, database, and table name are correct. |
| Connection refused / timeout | Check that the MySQL server accepts connections from Signal’s IP. Verify firewall rules, security groups, or authorised networks. |
Access denied for user | The username or password is incorrect, or the user cannot connect from Signal’s IP. Verify credentials and user host restriction. |
INSERT command denied | The user lacks INSERT privilege. Run GRANT INSERT ON db.table TO 'user'@'%';. |
Table doesn't exist | The table does not exist in the specified database. Verify the database and table names. |
| TLS connection errors | If use_tls is true, ensure the MySQL server has SSL enabled. For managed services, SSL is typically enabled by default. |
Data too long for column | An event field exceeds the column’s VARCHAR length. Increase the column size or check the data. |
| Character encoding issues | Ensure the table uses utf8mb4 character set and the connection character set matches. |
Visit MySQL documentation for full SQL reference, performance tuning, and replication setup.