Send Batch Commands
With GLIDE 2.0, Batch API replaces the previous Transaction API to support both atomic and non-atomic execution of commands in batches.
This guide will go over how to send commands in batches using the new Batch API.
To learn more on how GLIDE handles transactions and pipelining, see our article.
The Batch API
Section titled “The Batch API”In GLIDE 2.0, the Batch API provides a unified interface for handling both Transactions and Pipelining, allowing you to choose between strict consistency or high-throughput performance depending on your needs.
Making Transactions (Atomic Batch)
Section titled “Making Transactions (Atomic Batch)”A transaction is an all-or-nothing set of commands sent in a single request to Valkey. GLIDE handles this as atomic batches.
Standalone
Section titled “Standalone”from glide import ( GlideClientConfiguration, NodeAddress, GlideClient, BatchOptions,)
# Create client configurationaddresses = [ NodeAddress("server_primary.example.com", 6379), NodeAddress("server_replica.example.com", 6379)]config = GlideClientConfiguration(addresses)
# Initialize clientclient = await GlideClient.create(config)
# Configure batch optionsoptions = BatchOptions(timeout=2000)
# Create atomic batch (true indicates atomic/transaction mode)atomic_batch = Batch(True)atomic_batch.set("account:source", "100")atomic_batch.set("account:dest", "0")atomic_batch.incrby("account:dest", 50)atomic_batch.decrby("account:source", 50)atomic_batch.get("account:source")
try: # Execute with raiseOnError = true results = await client.exec(atomic_batch, raise_on_error=True, options=options) print("Atomic Batch Results:", results) # Expected output: Atomic Batch Results: ['OK', 'OK', 50, 50, '50'] except RequestError as e: print(f"Batch failed:", e)import glide.api.GlideClient;import glide.api.models.configuration.GlideClientConfiguration;import glide.api.models.Batch;import glide.api.models.BatchOptions;import glide.api.models.exceptions.RequestException;
// Create client configurationGlideClientConfiguration config = GlideClientConfiguration.builder() .address(NodeAddress.builder().host("localhost").port(6379).build()) .build();
// Initialize clientGlideClient client = GlideClient.createClient(config).get();
// Configure batch optionsBatchOptions options = BatchOptions.builder() .timeout(2000) // 2-second timeout .build();
// Create atomic batchBatch atomicBatch = new Batch(true) .set("account:source", "100") .set("account:dest", "0") .incrBy("account:dest", 50) .decrBy("account:source", 50) .get("account:source");
// Execute with raiseOnError = truetry { Object[] results = client.exec(atomicBatch, true, options).get(); System.out.println("Atomic Batch Results: " + Arrays.toString(results)); // Atomic Batch Results: ["OK", "OK", 50, 50, "50"]} catch (RequestException e) { System.err.println("Batch failed: " + e.getMessage());}import { GlideClient, Batch, BatchOptions } from "@valkey/valkey-glide";
// Create client configurationconst addresses = [ { host: "localhost", port: 6379, },];
// Initialize clientconst client = await GlideClient.createClient({ addresses: addresses });
// Configure batch optionsconst options : BatchOptions = { timeout: 2000 // 2-second timeout};
// Create atomic batch (true indicates atomic/transaction mode)const atomicBatch = new Batch(true) .set("account:source", "100") .set("account:dest", "0") .incrBy("account:dest", 50) .decrBy("account:source", 50) .get("account:source");
try { // Execute with raiseOnError = true const results = await client.exec(atomicBatch, true, options); console.log("Atomic Batch Results:", results); // Atomic Batch Results: ["OK", "OK", 50, 50, "50"]} catch (e) { console.error("Batch failed:", e.message);}import ( glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config" "github.com/valkey-io/valkey-glide/go/v2/pipeline")
// Create client configurationclientConf := config.NewClientConfiguration(). WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379})
// Initialize clientclient, _ := glide.NewClient(clientConf)
// Configure batch optionsoptions := pipeline.NewStandaloneBatchOptions(). WithTimeout(2 * time.Second) // 2-second timeout
// Create atomic batchtransaction := pipeline.NewStandaloneBatch(true). Set("account:source", "100"). Set("account:dest", "0"). IncrBy("account:dest", 50). DecrBy("account:source", 50). Get("account:source")
// Execute with raiseOnError = trueres, err := client.ExecWithOptions(ctx, *transaction, true, *options)if err != nil { fmt.Printf("Batch failed: %v\n", err)} else { fmt.Printf("Atomic Batch Results: %+v\n", res) // Atomic Batch Results: [OK OK 50 50 50]}Cluster
Section titled “Cluster”from glide import ( GlideClusterClientConfiguration, NodeAddress, GlideClusterClient, ClusterBatch, ClusterBatchOptions)
# Initialize cluster client configurationaddresses = [ NodeAddress("127.0.0.1", 6379)]config = GlideClusterClientConfiguration(addresses)
# Initialize clientglideClusterClient = await GlideClusterClient.create(config)
# Configure atomic batch optionsoptions = ClusterBatchOptions(timeout=3000) # 3-second timeout
# Create atomic cluster batch (all keys map to same slot)atomicClusterBatch = ClusterBatch(True)atomicClusterBatch.set("user:100:visits", "1")atomicClusterBatch.incrby("user:100:visits", 5)atomicClusterBatch.get("user:100:visits")
try: # Execute with raise_on_error = True clusterResults = await glideClusterClient.exec(atomicClusterBatch, raise_on_error=True, options=options) print("Atomic Cluster Batch:", clusterResults) # Expected output: Atomic Cluster Batch: ['OK', 6, '6']except RequestError as e: print("Atomic cluster batch failed:", e)import glide.api.models.ClusterBatch;import glide.api.models.ClusterBatchOptions;import glide.api.models.exceptions.RequestException;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.NodeAddress;import glide.api.GlideClusterClient;
// Initialize cluster clientGlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address( NodeAddress.builder() .host("127.0.0.1") .port(6379) .build() ) .build();
// Initialize clientGlideClusterClient glideClusterClient = GlideClusterClient.createClient(config).get();
// Configure atomic batch optionsClusterBatchOptions options = ClusterBatchOptions.builder() .timeout(3000) // 3-second timeout .build();
// Create atomic cluster batch (all keys map to same slot)ClusterBatch atomicClusterBatch = new ClusterBatch(true) .set("user:100:visits", "1") .incrBy("user:100:visits", 5) .get("user:100:visits");
// Execute with raiseOnError = truetry { Object[] clusterResults = glideClusterClient.exec(atomicClusterBatch, true, options).get(); System.out.println("Atomic Cluster Batch: " + Arrays.toString(clusterResults)); // Expected- Atomic Cluster Batch: ["OK", 6, "6"]} catch (RequestException e) { System.err.println("Atomic cluster batch failed: " + e.getMessage());}import { GlideClusterClient, ClusterBatch, ClusterBatchOptions } from "@valkey/valkey-glide";
// Initialize cluster client configurationconst addresses = [ { host: "127.0.0.1", port: 6379 }];
// Initialize clientconst glideClusterClient = await GlideClusterClient.createClient({ addresses: addresses });
// Configure atomic batch optionsconst options: ClusterBatchOptions = { timeout: 3000 // 3-second timeout};
// Create atomic cluster batch (all keys map to same slot)const atomicClusterBatch = new ClusterBatch(true) .set("user:100:visits", "1") .incrBy("user:100:visits", 5) .get("user:100:visits");
// Execute with raiseOnError = truetry { const clusterResults = await glideClusterClient.exec(atomicClusterBatch, true, options); console.log("Atomic Cluster Batch:", clusterResults); // Expected output: Atomic Cluster Batch: ["OK", 6, "6"]} catch (e) { console.error("Atomic cluster batch failed:", e);}import ( glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config" "github.com/valkey-io/valkey-glide/go/v2/pipeline")
// Create client configurationclientConf := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379})
// Initialize clientclient, _ := glide.NewClusterClient(clientConf)
// Configure batch optionsoptions := pipeline.NewClusterBatchOptions(). WithTimeout(3 * time.Second) // 3-second timeout
// Create atomic batchtransaction := pipeline.NewClusterBatch(true). Set("{user:100}:visits", "1"). IncrBy("{user:100}:visits", 5). Get("{user:100}:visits")
// Execute with raiseOnError = trueres, err := client.ExecWithOptions(ctx, *transaction, true, *options)if err != nil { fmt.Printf("Atomic cluster batch failed: %v\n", err)} else { fmt.Printf("Atomic Cluster Batch: %+v\n", res) // Atomic Cluster Batch Results: [OK 6 6]}Pipelining Commands (Non-Atomic Batch)
Section titled “Pipelining Commands (Non-Atomic Batch)”Pipelining is a group of commands sent in a single request that does not guarantee atomicity or isolation. GLIDE handles this as non-atomic batches.
Standalone
Section titled “Standalone”from glide import ( GlideClientConfiguration, NodeAddress, GlideClient, Batch, BatchOptions)
# Create client configurationaddresses = [ NodeAddress("localhost", 6379)]config = GlideClientConfiguration(addresses)
# Initialize clientclient = await GlideClient.create(config)
# Configure batch optionsoptions = BatchOptions(timeout=2000) # 2-second timeout
# Create non-atomic batch (False indicates pipeline mode)pipeline = Batch(False)pipeline.set("temp:key1", "value1")pipeline.set("temp:key2", "value2")pipeline.get("temp:key1")pipeline.get("temp:key2")
# Execute with raise_on_error = Falseresults = await client.exec(pipeline, raise_on_error=False, options=options)print("Pipeline Results:", results)# Expected output: Pipeline Results: ['OK', 'OK', 'value1', 'value2']import glide.api.GlideClient;import glide.api.models.Batch;import glide.api.models.BatchOptions;
// Create client configurationGlideClientConfiguration config = GlideClientConfiguration.builder() .address(NodeAddress.builder().host("localhost").port(6379).build()) .build();
// Initialize clientGlideClient client = GlideClient.createClient(config).get();
// Configure batch optionsBatchOptions options = BatchOptions.builder() .timeout(2000) // 2-second timeout .build();
Batch pipeline = new Batch(false) .set("temp:key1", "value1") .set("temp:key2", "value2") .get("temp:key1") .get("temp:key2");
Object[] results = client.exec(pipeline, false, options).get();System.out.println("Pipeline Results: " + Arrays.toString(results));// Pipeline Results: ["OK", "OK", "value1", "value2"]import { GlideClient, Batch, BatchOptions} from "@valkey/valkey-glide";
// Create client configurationconst addresses = [ { host: "localhost", port: 6379, },];
// Initialize clientconst client = await GlideClient.createClient({ addresses: addresses });
// Configure batch optionsconst options : BatchOptions = { timeout: 2000 // 2-second timeout};
// Create non-atomic batch (false indicates pipeline mode)const pipeline = new Batch(false) .set("temp:key1", "value1") .set("temp:key2", "value2") .get("temp:key1") .get("temp:key2");
// Execute with raiseOnError = falseconst results = await client.exec(pipeline, false, options);console.log("Pipeline Results:", results);// Pipeline Results: ["OK", "OK", "value1", "value2"]import ( glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config" "github.com/valkey-io/valkey-glide/go/v2/pipeline")
// Create client configurationclientConf := config.NewClientConfiguration(). WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379})
// Initialize clientclient, _ := glide.NewClient(clientConf)
// Configure batch optionsoptions := pipeline.NewStandaloneBatchOptions(). WithTimeout(2 * time.Second) // 2-second timeout
// Create non-atomic batchpipeline := pipeline.NewStandaloneBatch(false). Set("temp:key1", "value1"). Set("temp:key2", "value2"). Get("temp:key1"). Get("temp:key2")
res, err := client.ExecWithOptions(ctx, *pipeline, false, *options)fmt.Printf("Pipeline Results: %+v\n", res)// Pipeline Results: [OK OK value1 value2]Cluster
Section titled “Cluster”from glide import ( GlideClusterClientConfiguration, NodeAddress, GlideClusterClient, ClusterBatch, ClusterBatchOptions, ClusterBatchRetryStrategy)
# Initialize cluster client configurationaddresses = [ NodeAddress("localhost", 6379)]config = GlideClusterClientConfiguration(addresses)
# Initialize clientglideClusterClient = await GlideClusterClient.create(config)
# Configure retry strategy and pipeline optionsretry_strategy = ClusterBatchRetryStrategy( retry_server_error=False, retry_connection_error=True)
pipeline_options = ClusterBatchOptions( timeout=5000, # 5-second timeout retry_strategy=retry_strategy)
# Create pipeline spanning multiple slotspipeline_cluster = ClusterBatch(False) # False indicates non-atomic (pipeline)pipeline_cluster.set("page:home:views", "100")pipeline_cluster.incrby("page:home:views", 25)pipeline_cluster.get("page:home:views")pipeline_cluster.lpush("recent:logins", ["user1"])pipeline_cluster.lpush("recent:logins", ["user2"])pipeline_cluster.lrange("recent:logins", 0, 1)
# Execute with raise_on_error = Falsepipeline_results = await glideClusterClient.exec(pipeline_cluster, raise_on_error=False, options=pipeline_options)print("Pipeline Cluster Results:", pipeline_results)# Expected output: Pipeline Cluster Results: ['OK', 125, '125', 1, 2, ['user2', 'user1']]import glide.api.models.ClusterBatch;import glide.api.models.ClusterBatchOptions;import glide.api.models.commands.batch.ClusterBatchRetryStrategy;import glide.api.models.configuration.GlideClusterClientConfiguration;import glide.api.models.NodeAddress;import glide.api.GlideClusterClient;
// Initialize cluster clientGlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder() .address( NodeAddress.builder() .host("localhost") .port(6379) .build() ) .build();
GlideClusterClient glideClusterClient = GlideClusterClient.createClient(config).get();
// Configure retry strategy and pipeline optionsClusterBatchRetryStrategy retryStrategy = ClusterBatchRetryStrategy.builder() .retryServerError(false) .retryConnectionError(true) .build();
ClusterBatchOptions pipelineOptions = ClusterBatchOptions.builder() .timeout(5000) // 5-second timeout .retryStrategy(retryStrategy) .build();
// Create pipeline spanning multiple slotsClusterBatch pipelineCluster = new ClusterBatch(false) .set("page:home:views", "100") .incrBy("page:home:views", 25) .get("page:home:views") .lpush("recent:logins", "user1") .lpush("recent:logins", "user2") .lrange("recent:logins", 0, 1);
// Execute with raiseOnError = falseObject[] pipelineResults = glideClusterClient.exec(pipelineCluster, false, pipelineOptions).get();System.out.println("Pipeline Cluster Results: " + Arrays.toString(pipelineResults));// Pipeline Cluster Results: ["OK", 125, "125", 1, 2, ["user2", "user1"]]import { GlideClusterClient, ClusterBatch, ClusterBatchOptions, ClusterBatchRetryStrategy } from "@valkey/valkey-glide";// Initialize cluster client configurationconst addresses = [ { host: "localhost", port: 6379 }];
// Initialize clientconst glideClusterClient = await GlideClusterClient.createClient({ addresses : addresses });
// Configure retry strategy and pipeline optionsconst retryStrategy : ClusterBatchRetryStrategy = { retryServerError: false, retryConnectionError: true};
const pipelineOptions : ClusterBatchOptions = { timeout: 5000, // 5-second timeout retryStrategy: retryStrategy};
// Create pipeline spanning multiple slotsconst pipelineCluster = new ClusterBatch(false) // false indicates non-atomic (pipeline) .set("page:home:views", "100") .incrBy("page:home:views", 25) .get("page:home:views") .lpush("recent:logins", ["user1"]) .lpush("recent:logins", ["user2"]) .lrange("recent:logins", 0, 1);
// Execute with raiseOnError = falseconst pipelineResults = await glideClusterClient.exec(pipelineCluster, false, pipelineOptions);console.log("Pipeline Cluster Results:", pipelineResults);// Expected output: Pipeline Cluster Results: ["OK", 125, "125", 1, 2, ["user2", "user1"]]import ( glide "github.com/valkey-io/valkey-glide/go/v2" "github.com/valkey-io/valkey-glide/go/v2/config" "github.com/valkey-io/valkey-glide/go/v2/pipeline")
// Create client configurationclientConf := config.NewClusterClientConfiguration(). WithAddress(&config.NodeAddress{Host: "localhost", Port: 6379})
// Initialize clientclient, _ := glide.NewClusterClient(clientConf)
// Configure retry strategy and pipeline optionsretryStrategy := pipeline.NewClusterBatchRetryStrategy(). WithRetryConnectionError(true). WithRetryServerError(false)
options := pipeline.NewClusterBatchOptions(). WithTimeout(5 * time.Second). // 5-second timeout WithRetryStrategy(retryStrategy)
// Create pipeline spanning multiple slotspipeline := pipeline.NewClusterBatch(false). Set("page:home:views", "100"). IncrBy("page:home:views", 25). Get("page:home:views"). Lpush("recent:logins", "user1"). Lpush("recent:logins", "user2"). Lrange("recent:logins", 0, 1)
// Execute with raiseOnError = falseres, err := client.ExecWithOptions(ctx, *pipeline, false, *options)fmt.Printf("Pipeline Cluster Results: %+v\n", res)// Pipeline Cluster Results: [OK 125 125 1 2 [user2 user1]]Next Steps
Section titled “Next Steps”To lean more about how GLIDE handles batch commands, see our explanation.