# How to Use MySQL connectionAttributes in Go: Complete Implementation Guide

> Learn how to use MySQL connectionAttributes in Go with a complete implementation guide. Understand how this driver feature enables custom context and metadata reporting.

- Repository: [Go SQL Drivers/mysql](https://github.com/go-sql-driver/mysql)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Connection attributes are key-value pairs that the client transmits to the MySQL server during the initial handshake, enabling automatic metadata reporting and custom application context injection.**

The `go-sql-driver/mysql` package manages **connection attributes** through a three-stage pipeline that parses DSN parameters, encodes them into a length-prefixed binary format, and conditionally transmits them during authentication. Understanding this mechanism allows developers to inject application-specific telemetry that can be inspected via `performance_schema` tables for debugging and audit trails.

## What Are MySQL connectionAttributes?

Connection attributes serve two distinct functions in the MySQL protocol:

- **Automatic Metadata Reporting**: The driver always includes default runtime information such as the client library name and version, operating system (`runtime.GOOS`), platform architecture, and process ID (`os.Getpid`).
- **Custom Context Injection**: Developers can append arbitrary key-value pairs—such as application name, deployment environment, or request tracing IDs—that propagate to server-side monitoring tables.

These attributes are only transmitted if the server advertises the `CLIENT_CONNECT_ATTRS` capability flag during the initial handshake. If unsupported, the driver silently omits the attribute block without raising an error.

## How the Go MySQL Driver Manages connectionAttributes

The driver implements connection attribute handling across three source files, ensuring efficient encoding and caching.

### Stage 1: DSN Parsing and Config Storage

When parsing a Data Source Name (DSN), the driver extracts the `connectionAttributes` parameter and stores it as a raw comma-delimited string in the `Config` struct.

In [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go), the `Config` struct defines the field:

```go
// Config contains the mysql driver configuration.
type Config struct {
    // ... other fields ...
    ConnectionAttributes string // connection attributes, comma-delimited "key:value" pairs
}

```

The value remains as a string at this stage (e.g., `"app_name:MyApp,app_version:1.2.3"`), awaiting encoding during connector initialization.

### Stage 2: Encoding and Caching

The `connector` type in [`connector.go`](https://github.com/go-sql-driver/mysql/blob/main/connector.go) handles the transformation of these attributes into the MySQL wire format. The `encodeConnectionAttributes` function constructs a byte slice that begins with default attributes and appends user-defined pairs.

Key implementation details from [`connector.go`](https://github.com/go-sql-driver/mysql/blob/main/connector.go):

- **Default attributes** are automatically generated from the runtime environment.
- **User-defined attributes** are split on commas, with each `"key:value"` pair being length-encoded according to the MySQL protocol.
- The resulting byte slice is cached in `connector.encodedAttributes` to avoid recomputation for every new connection.

This caching strategy ensures that the encoding cost is paid once per DSN configuration rather than per connection.

### Stage 3: Handshake Transmission

During the authentication sequence, the driver conditionally includes the encoded attributes in the client response packet. In [`packets.go`](https://github.com/go-sql-driver/mysql/blob/main/packets.go), the `writeHandshakeResponsePacket` function checks for server capability support:

```go
// Only write connection attributes if the server supports CLIENT_CONNECT_ATTRS
if mc.cfg.capabilities&CLIENT_CONNECT_ATTRS != 0 {
    // Write encodedAttributes length and payload
    // ...
}

```

If `CLIENT_CONNECT_ATTRS` is present in the server's capability flags, the pre-encoded byte slice from `connector.encodedAttributes` is written to the packet buffer.

## Implementing connectionAttributes in Your Application

You can specify connection attributes either via DSN string or by configuring the `Config` struct directly.

### Using a DSN String

Append the `connectionAttributes` query parameter with comma-separated `key:value` pairs:

```go
package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    dsn := "user:password@tcp(localhost:3306)/dbname?" +
        "connectionAttributes=app_name:MyApp,app_version:1.2.3,env:staging"
    
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    fmt.Println("Database opened with custom connection attributes")
}

```

### Using the Config Struct

For programmatic configuration, set the `ConnectionAttributes` field before formatting the DSN:

```go
cfg := mysql.NewConfig()
cfg.User = "user"
cfg.Passwd = "password"
cfg.Net = "tcp"
cfg.Addr = "localhost:3306"
cfg.DBName = "dbname"
cfg.ConnectionAttributes = "app_name:MyApp,app_version:1.2.3,env:staging"

db, err := sql.Open("mysql", cfg.FormatDSN())

```

Both methods result in identical binary payloads being transmitted during the handshake.

## Verifying Attributes on the Server Side

To confirm that attributes are reaching the server, query the `performance_schema.session_account_connect_attrs` table:

```sql
SELECT ATTR_NAME, ATTR_VALUE
FROM performance_schema.session_account_connect_attrs
WHERE PROCESSLIST_ID = CONNECTION_ID();

```

This displays both the driver's default attributes (such as `_client_name` and `_pid`) and your custom application keys.

## Summary

- **connectionAttributes** enable bi-directional metadata transparency between Go applications and MySQL servers.
- The driver manages attributes through a three-stage lifecycle: DSN parsing in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go), encoding and caching in [`connector.go`](https://github.com/go-sql-driver/mysql/blob/main/connector.go) via `encodeConnectionAttributes`, and conditional transmission in [`packets.go`](https://github.com/go-sql-driver/mysql/blob/main/packets.go).
- Default attributes (OS, PID, client version) are always included automatically.
- User-defined attributes use a comma-delimited `key:value` syntax in the DSN.
- The encoded attribute block is cached per-connector to optimize connection pooling performance.
- Transmission only occurs if the server supports the `CLIENT_CONNECT_ATTRS` capability.

## Frequently Asked Questions

### What is the correct format for specifying connectionAttributes in the DSN?

The `connectionAttributes` parameter accepts a comma-delimited string where each element follows the `key:value` format. For example: `connectionAttributes=app_name:MyApp,region:us-east-1`. Do not include spaces around the colons or commas, as the parser treats the entire string literally before splitting.

### Are connectionAttributes supported by all MySQL server versions?

No. Connection attributes require MySQL 5.6 or later, or compatible forks that implement the `CLIENT_CONNECT_ATTRS` capability. If the server does not advertise this capability during the handshake, the `go-sql-driver/mysql` driver automatically omits the attribute block without throwing an error, ensuring backward compatibility.

### How can I verify that my connection attributes are being sent correctly?

Query the `performance_schema.session_account_connect_attrs` table on the MySQL server, filtering by your current connection ID. Alternatively, inspect the `information_schema.PROCESSLIST` and related tables if `performance_schema` is disabled, though attribute inspection specifically requires `performance_schema` tables.

### Is there a performance overhead when using connectionAttributes?

The overhead is negligible. The driver encodes attributes once during connector initialization and caches the result in `connector.encodedAttributes`. This pre-encoded byte slice is reused for every connection established from that configuration, meaning the encoding cost is not incurred per connection. The additional network payload is typically under a few hundred bytes.