-
Notifications
You must be signed in to change notification settings - Fork 112
Golang wrapper
Please refer to the README of the Go examples for the instructions on how to run Standalone Example and Cluster Example.
Valkey GLIDE provides support for both Cluster and Standalone configurations. Please refer to the relevant section based on your specific setup.
Valkey GLIDE supports Cluster deployments, where the database is partitioned across multiple primary shards, with each shard being represented by a primary node and zero or more replica nodes.
To initialize a ClusterClient, you need to provide a ClusterClientConfiguration that includes the addresses of initial seed nodes. Valkey GLIDE automatically discovers the entire cluster topology, eliminating the necessity of explicitly listing all cluster nodes.
The NodeAddress struct represents the host and port of a cluster node. The host can be either an IP address, a hostname, or a fully qualified domain name (FQDN).
import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectCluster() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379})
client, err := glide.NewClusterClient(myConfig)
}In the cluster, data is divided into slots, and each primary node within the cluster is responsible for specific slots. Valkey GLIDE adheres to Valkey OSS guidelines when determining the node(s) to which a command should be sent in clustering mode.
For more details on the routing of specific commands, please refer to the documentation within the code for routing configuration.
When requests are dispatched to multiple shards in a cluster (as discussed in the Request routing section), the client needs to aggregate the responses for a given command. Valkey GLIDE follows Valkey OSS guidelines for determining how to aggregate the responses from multiple shards within a cluster.
To learn more about response aggregation for specific commands, please refer to the documentation within the code.
The cluster's topology can change over time. New nodes can be added or removed, and the primary node owning a specific slot may change. Valkey GLIDE is designed to automatically rediscover the topology whenever the server indicates a change in slot ownership. This ensures that the Valkey GLIDE client stays in sync with the cluster's topology.
Valkey GLIDE also supports Standalone deployments, where the database is hosted on a single primary node, optionally with replica nodes. To initialize a Client for a standalone setup, you should create a ClientConfiguration that includes the addresses of primary and all replica nodes.
import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectStandalone() {
myConfig := config.NewClientConfiguration().
WithAddress(&config.NodeAddress{Host: "primary.example.com", Port: 6379}).
WithAddress(&config.NodeAddress{Host: "replica1.example.com", Port: 6379}).
WithAddress(&config.NodeAddress{Host: "replica2.example.com", Port: 6379})
client, err := glide.NewClient(myConfig)
}For information on the supported commands and their corresponding parameters, we recommend referring to the documentation in the code. This documentation provides in-depth insights into the usage and options available for each command.
A transaction in Valkey GLIDE allows you to execute a group of commands in a single, atomic step. This ensures that all commands in the transaction are executed sequentially and without interruption. See Valkey Transactions.
This is equivalent to the Valkey commands MULTI / EXEC.
See Valkey Batch Release notes for more details about the design and implementation.
GLIDE 1.3 introduces a new NONE Valkey API: Info which returns a string with many relevant properties (available for both Client & ClusterClient). See descriptions for the Section type in constants.
import (
"context"
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func UseInfo() {
myConfig := config.NewClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379})
client, _ := glide.NewClient(myConfig)
result, _ := client.Info(context.Background())
// do something with the `stats`
}Observability is consistently one of the top feature requests by customers. Valkey GLIDE 2.0 introduces support for OpenTelemetry (OTel), enabling developers to gain deep insights into client-side performance and behavior in distributed systems. OTel is an open source, vendor-neutral framework that provides APIs, SDKs, and tools for generating, collecting, and exporting telemetry data—such as traces, metrics, and logs. It supports multiple programming languages and integrates with various observability backends like Prometheus, Jaeger, and AWS CloudWatch.
GLIDE's OpenTelemetry integration is designed to be both powerful and easy to adopt. Once an OTel collector endpoint is configured, GLIDE begins emitting default metrics and traces automatically—no additional code changes are required. This simplifies the path to observability best practices and minimizes disruption to existing workflows.
GLIDE emits several built-in metrics out of the box. These metrics can be used to build dashboards, configure alerts, and monitor performance trends:
- Timeouts: Number of requests that exceeded their timeout duration.
- Retries: Count of operations retried due to transient errors or topology changes.
- Moved Errors: Number of MOVED responses received, indicating key reallocation in the cluster.
These metrics are emitted to your configured OpenTelemetry collector and can be viewed in any supported backend (Prometheus, CloudWatch, etc.).
GLIDE creates a trace span for each Valkey command, giving detailed visibility into client-side performance. Each trace captures:
- The entire command lifecycle: from creation to completion or failure.
- A nested
send_commandspan, measuring communication time with the Valkey server. - A status tag indicating success or error for each span, helping you identify failure patterns.
This distinction helps developers separate client-side queuing latency from server communication delays, making it easier to troubleshoot performance issues.
⚠ Note: Some advanced commands are not yet included in tracing instrumentation:
- The SCAN family of commands (SCAN, SSCAN, HSCAN, ZSCAN)
- Lua scripting commands (EVAL, EVALSHA)
Support for these commands will be added in a future version as we continue to expand tracing coverage.
Even with these exceptions, GLIDE 2.0 provides comprehensive insights across the vast majority of standard operations, making it easy to adopt observability best practices with minimal effort.
To begin collecting telemetry data with GLIDE 2.0:
- Set up an OpenTelemetry Collector to receive trace and metric data.
- Configure the GLIDE client with the endpoint to your collector.
GLIDE does not export data directly to third-party services—instead, it sends data to your collector, which routes it to your backend (e.g., CloudWatch, Prometheus, Jaeger).
You can configure the OTel collector endpoint using one of the following protocols:
-
http://orhttps://- Send data via HTTP(S) -
grpc://- Use gRPC for efficient telemetry transmission -
file://- Write telemetry data to a local file (ideal for local dev/debugging)
When initializing OpenTelemetry, you can customize behavior using the openTelemetryConfig object.
Note: Both traces and metrics are optional—but at least one must be provided in the openTelemetryConfig. If neither is set, OpenTelemetry will not emit any data.
openTelemetryConfig.traces- endpoint (required): The trace collector endpoint.
-
samplePercentage (optional): Percentage (0–100) of commands to sample for tracing. Default:
1.- For production, a low sampling rate (1–5%) is recommended to balance performance and insight.
openTelemetryConfig.metrics- endpoint (required): The metrics collector endpoint.
openTelemetryConfig.flushIntervalMs- (optional): Time in milliseconds between flushes to the collector. Default:
5000.
If using file:// as the endpoint:
- The path must begin with
file://. - If a directory is provided (or no file extension), data is written to
signals.jsonin that directory. - If a filename is included, it will be used as-is.
- The parent directory must already exist.
- Data is appended, not overwritten.
-
flushIntervalMsmust be a positive integer. -
samplePercentagemust be between 0 and 100. - File exporter paths must start with
file://and have an existing parent directory. - Invalid configuration will throw an error synchronously when calling
OpenTelemetry.init().
OpenTelemetry.init() can only be called once per process. Subsequent calls will be ignored. To change configuration, restart the process.
import "github.com/valkey-io/valkey-glide/go/v2"
config := glide.OpenTelemetryConfig{
Traces: &glide.OpenTelemetryTracesConfig{
Endpoint: "http://localhost:4318/v1/traces",
SamplePercentage: 10, // Optional, defaults to 1. Can also be changed at runtime via `SetSamplePercentage()`
},
Metrics: &glide.OpenTelemetryMetricsConfig{
Endpoint: "http://localhost:4318/v1/metrics",
},
FlushIntervalMs: &interval, // Optional, defaults to 5000, e.g. interval := int64(1000)
}
err := glide.GetOtelInstance().Init(config)
if err != nil {
log.Fatalf("Failed to initialize OpenTelemetry: %v", err)
}By default, when connecting to Valkey, Valkey GLIDE operates in an unauthenticated mode.
Valkey GLIDE also offers support for an authenticated connection mode.
In authenticated mode, you have the following options:
- Use both a username and password, which is recommended and configured through ACLs on the server.
- Use a password only, which is applicable if the server is configured with the requirepass setting.
To provide the necessary authentication credentials to the client, you can use the ServerCredentials struct.
import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithCredentials() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithCredentials(config.NewServerCredentials("user1", "passwordA"))
client, err := glide.NewClusterClient(myConfig)
}import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectStandaloneWithCredentials() {
myConfig := config.NewClientConfiguration().
WithAddress(&config.NodeAddress{Host: "primary.example.com", Port: 6379}).
WithCredentials(config.NewServerCredentials("user1", "passwordA"))
client, err := glide.NewClient(myConfig)
}Valkey GLIDE supports secure TLS connections to a data store.
It's important to note that TLS support in Valkey GLIDE relies on rustls. Currently, Valkey GLIDE employs the default rustls settings with no option for customization.
import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithTLS() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithUseTLS(true)
client, err := glide.NewClusterClient(myConfig)
}import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectStandaloneWithTLS() {
myConfig := config.NewClientConfiguration().
WithAddress(&config.NodeAddress{Host: "primary.example.com", Port: 6379}).
WithUseTLS(true)
client, err := glide.NewClient(myConfig)
}By default, Valkey GLIDE directs read commands to the primary node that owns a specific slot. For applications that prioritize read throughput and can tolerate possibly stale data, Valkey GLIDE provides the flexibility to route reads to replica nodes.
Valkey GLIDE provides support for next read strategies, allowing you to choose the one that best fits your specific use case.
| Strategy | Description |
|---|---|
Primary |
Always read from primary, in order to get the freshest data. |
PreferReplica |
Spread requests between all replicas in a round robin manner. If no replica is available, route the requests to the primary. |
AZAffinity |
Spread the read requests between replicas in the same client's availability zone in a round robin manner, falling back to other replicas or the primary if needed. |
AzAffinityReplicaAndPrimary |
Spread the read requests among nodes within the client's Availability Zone (AZ) in a round robin manner, prioritizing local replicas, then the local primary, and falling back to any replica or the primary if needed. |
import (
"context"
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithReadStrategyPreferReplica() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithReadFrom(config.PreferReplica)
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get will read from one of the replicas
client.Get(context.Background(),"key1")
}If ReadFrom strategy is AZAffinity, 'clientAZ' setting is required to ensures that readonly commands are directed to replicas within the specified AZ if exits.
import (
"context"
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithReadStrategyAZAffinity() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithReadFrom(config.AzAffinity).
WithClientAZ("us-east-1a")
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get will read from one of the replicas in the same client's availability zone if exits.
client.Get(context.Background(),"key1")
}If ReadFrom strategy is AzAffinityReplicaAndPrimary, 'clientAZ' setting is required to ensures that readonly commands are directed to replicas or primary within the specified AZ if exits.
import (
"context"
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithReadStrategyAZAffinity() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithReadFrom(config.AzAffinityReplicaAndPrimary).
WithClientAZ("us-east-1a")
client, _ := glide.NewClusterClient(myConfig)
client.Set(context.Background(), "key1", "val1")
// Get will read from one of the replicas or the primary in the same client's availability zone if exits.
client.Get(context.Background(),"key1")
}Valkey GLIDE allows you to configure timeout settings and reconnect strategies. These configurations can be applied through the ClusterClientConfiguration and ClientConfiguration parameters.
| Configuration setting | Description | Default value |
|---|---|---|
| requestTimeout | This specified time duration, measured in milliseconds, represents the period during which the client will await the completion of a request. This time frame includes the process of sending the request, waiting for a response from the node(s), and any necessary reconnection or retry attempts. If a pending request exceeds the specified timeout, it will trigger a timeout error. If no timeout value is explicitly set, a default value will be employed. | 250 milliseconds |
| reconnectStrategy | The reconnection strategy defines how and when reconnection attempts are made in the event of connection failures. | Exponential backoff |
import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func ConnectClusterWithTimeout() {
myConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithRequestTimeout(500)
client, err := glide.NewClusterClient(myConfig)
}import (
glide "github.com/valkey-io/valkey-glide/go/v2"
"github.com/valkey-io/valkey-glide/go/v2/config"
)
func FullConfigExample() {
// GlideClient example
standaloneConfig := config.NewClientConfiguration().
WithAddress(&config.NodeAddress{Host: "primary.example.com", Port: 6379}).
WithClientName("some client name").
WithCredentials(config.NewServerCredentials("user1", "passwordA")).
WithDatabaseId(1).
WithReadFrom(config.PreferReplica).
WithReconnectStrategy(config.NewBackoffStrategy(5, 10, 50)).
WithRequestTimeout(500).
WithUseTLS(true)
standaloneClient, err := glide.NewClient(standaloneConfig)
// GlideClusterClient example
clusterConfig := config.NewClusterClientConfiguration().
WithAddress(&config.NodeAddress{Host: "address.example.com", Port: 6379}).
WithClientName("some client name").
WithCredentials(config.NewServerCredentials("user1", "passwordA")).
WithReadFrom(config.PreferReplica).
WithRequestTimeout(500).
WithUseTLS(true)
clusterClient, err := glide.NewClusterClient(clusterConfig)
}