How to Use MySQL connectionAttributes in Go: Complete Implementation Guide

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, the Config struct defines the field:

// 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 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:

  • 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, the writeHandshakeResponsePacket function checks for server capability support:

// 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:

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:

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:

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, encoding and caching in connector.go via encodeConnectionAttributes, and conditional transmission in 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →