> ## Documentation Index
> Fetch the complete documentation index at: https://help.statisfy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL Integration

> Connect a MySQL database to Statisfy to sync product usage, custom fields, and custom objects with self-serve query configuration.

### Connect MySQL with Statisfy

The MySQL integration lets you import data from any MySQL-compatible database into Statisfy — your application database, an analytics replica, or a MySQL-wire-compatible engine such as MariaDB. Author SQL queries in the Statisfy settings UI, preview results, and schedule them.

MySQL uses the same self-serve configuration model as the other warehouse integrations. You can find the shared concepts — query types, account resolvers, transformers, schedules, configuration history — in [Integration Concepts](/integrations/self_serve_configuration). This page focuses on what's specific to MySQL.

**Prerequisites:**

* **Admin access** to Statisfy
* A MySQL instance reachable from Statisfy's egress IPs (see [Network Access](#network-access))
* **TLS enabled** on the MySQL server — Statisfy requires an encrypted connection and refuses to connect otherwise (see [TLS requirement](#tls-requirement))
* A database user with `SELECT` access on the tables you want to sync

### What You Can Import

| Data Type          | Description                           | Use Case                                     |
| ------------------ | ------------------------------------- | -------------------------------------------- |
| **Product Usage**  | Time-series usage metrics per account | MAU, API calls, feature usage                |
| **Custom Fields**  | Account- or person-level attributes   | Health scores, segments, industry, plan tier |
| **Custom Objects** | Domain-specific records               | Subscriptions, deployments, contracts        |

### Set Up the Database User

Run as a MySQL admin user (or any user with `CREATE USER` and `GRANT` privileges):

```sql theme={null}
-- 1. Create a dedicated read-only user
CREATE USER 'statisfy_reader'@'%' IDENTIFIED BY '<set-and-store-securely>';

-- 2. Grant read access on the database(s) Statisfy should see
GRANT SELECT ON analytics.* TO 'statisfy_reader'@'%';

-- 3. Apply the changes
FLUSH PRIVILEGES;
```

Replace `analytics` with the database you want Statisfy to read. To restrict the user to specific tables, grant `SELECT` per table (`GRANT SELECT ON analytics.usage_events TO ...`) instead of using the wildcard.

<Tip>
  If you can, point Statisfy at a **read replica** rather than your primary database. Sync queries can be large; a replica isolates that load from your live application traffic.
</Tip>

### Steps to Connect

1. **Log in to Statisfy.**

2. Navigate to **Integrations → Admin Apps → MySQL → Connect**.

3. Enter your connection details:
   * **Host** — DNS name or IP of the database
   * **Port** — Default `3306`
   * **Database** — Database name
   * **Username** — `statisfy_reader` (or whichever read-only user you created)
   * **Password** — The user's password

4. Click **Test Connection** to confirm Statisfy can reach the host and authenticate.

5. Once connected, MySQL will appear as **Connected** on the Integrations page.

### Configure Queries

Open **Integrations → MySQL → Settings** to:

* **Browse schemas and tables** the user can see, with column types
* **Author queries** using MySQL SQL with autocomplete and a preview pane
* **Map results** to Statisfy accounts (via Statisfy account ID, CRM ID, organization ID, email domain, account name, or any custom field) and to fields, metrics, or custom objects
* **Apply column transformers** (`strip_prefix`, `regex_extract`, `lookup`, etc.) to reshape values before they're written
* **Set the cadence** — daily, weekly, monthly, or a sub-day interval (HOURLY through TWELVE\_HOURS)
* **Run a one-off sync** on demand

Each saved query is one of three types — `product_usage`, `custom_field`, or `custom_object`. See [Query types](/integrations/self_serve_configuration#query-types) and [Account resolvers](/integrations/self_serve_configuration#account-resolvers) for the shared model.

### MySQL-Specific Notes

* **Date placeholders.** Use `{START_DATE}` / `{END_DATE_SQL}` in `WHERE` clauses to keep queries incremental. MySQL's `DATE()`, `DATE_SUB()`, and `DATE_FORMAT()` compose naturally with these.
* **Database as namespace.** MySQL treats "database" and "schema" as the same thing. Queries that reference tables outside the connected database should qualify them explicitly (`other_db.table`), and the user needs `SELECT` on those databases too.
* **Identifier quoting.** MySQL uses backticks (`` `column` ``) rather than double quotes for identifiers that clash with reserved words.

### Account Matching

| Resolver                | Description                              |
| ----------------------- | ---------------------------------------- |
| **Statisfy Account ID** | Native Statisfy account identifier       |
| **CRM Account ID**      | Salesforce or HubSpot account identifier |
| **Organization ID**     | External org identifier                  |
| **Email Domain**        | Company website domain                   |
| **Account Name**        | Company name (fuzzy matching)            |
| **Custom Field**        | Any custom field defined on accounts     |

<Warning>
  Rows that don't resolve to an existing Statisfy account are skipped. For CRM ID resolvers, make sure your CRM integration has synced the matching accounts first.
</Warning>

For `custom_field` queries that target people instead of accounts, configure a **person resolver** (email column, optionally name) — Statisfy will upsert the person record by email.

### Sync Behavior

**Scheduled Jobs:**

* Each saved query runs on its own cadence.
* The first run after connecting is a **bootstrap** covering the last 30 days; subsequent runs cover only the active window for the cadence.
* Self-serve configuration takes precedence over any built-in fallback set up by support.

**Error Handling:**

* Per-query errors are logged but do not block other queries from running.
* Invalid rows within a query are skipped and reported in the job audit log.

### TLS Requirement

TLS (Transport Layer Security) is the standard protocol for securing a network connection: it encrypts the traffic between two systems and, when fully configured, verifies each side's identity — so a connection can't be read or impersonated in transit.

Statisfy always connects over TLS and verifies the server actually negotiated an encrypted session before running any query — if it didn't, the connection is refused rather than silently falling back to plaintext. This protects your credentials and data in transit, since Statisfy is connecting to a database it doesn't operate.

<Note>
  This does not verify the server's certificate or hostname (there's no CA to check it against for an arbitrary customer-supplied host) — it only guarantees the session is encrypted, not that you're connected to the server you think you are. No control on Statisfy's side authenticates server identity for this connector.
</Note>

If your MySQL server doesn't have TLS enabled, enable it before connecting (for example, `require_secure_transport=ON` plus a valid certificate on the server) — there is no way to opt out of this requirement.

### Network Access

If your MySQL host has IP allowlisting or is in a private network, allow Statisfy's egress IPs:

```text theme={null}
35.203.185.27
35.197.52.231
```

If your database isn't reachable from the public internet, reach out to [support@statisfy.com](mailto:support@statisfy.com) to discuss VPN / SSH-tunnel options.

### Security

* Credentials are stored encrypted in Google Cloud Secret Manager.
* Queries authored in the Settings page are read-only — Statisfy validates each query and rejects DDL/DML before save.
* Access is scoped to the database user you provide — grant `SELECT` only on the databases and tables you want Statisfy to read.

### Troubleshooting

<Accordion title="Connection test fails">
  **Check network access:**

  * Verify the host is reachable from the Statisfy egress IPs above
  * Confirm the firewall / security group allows inbound traffic on the MySQL port (default `3306`)

  **Check credentials:**

  * Verify host, port, database, username, and password
  * Confirm the user's host pattern allows remote connections (`'statisfy_reader'@'%'`, not `'statisfy_reader'@'localhost'`)

  **"did not negotiate TLS" error:**

  * Enable TLS on the MySQL server — see [TLS Requirement](#tls-requirement). This is a mandatory configuration, and it needs to be configured by your network admin.
</Accordion>

<Accordion title="Schema or tables not visible in the browser">
  * Confirm the database user has `SELECT` on the tables
  * System schemas (`information_schema`, `mysql`, `performance_schema`, `sys`) are intentionally hidden
  * New grants may require closing and reopening the schema picker
</Accordion>

<Accordion title="Query validation errors at save time">
  * Statisfy validates queries against the MySQL dialect — vendor-specific functions from other warehouses will be flagged
  * DDL (`CREATE`, `DROP`, `ALTER`) and DML (`INSERT`, `UPDATE`, `DELETE`) are rejected — only read-only queries are allowed
  * Check the validation error for the offending function or syntax
</Accordion>

<Accordion title="Records not matching to accounts">
  * Verify the resolver column contains values that exist in Statisfy
  * For CRM ID resolvers, confirm your CRM integration has synced the matching accounts
  * Try a different resolver (switch from account name to email domain) if matching is unreliable
  * Add a `regex_extract` or `strip_prefix` transformer if the column contains the right ID with extra characters
</Accordion>

<Accordion title="Sync is slow or impacting production">
  * Point Statisfy at a **read replica** instead of the primary
  * Lower the cadence to `DAILY` so each run scans a smaller window
  * Use `{START_DATE}` / `{END_DATE_SQL}` to keep queries incremental
  * Add indexes on the columns you filter on
</Accordion>

### Need Help?

For initial setup, query design, or troubleshooting, contact [support@statisfy.com](mailto:support@statisfy.com).
