Throughput optimized writes Stay organized with collections Save and categorize content based on your preferences.
This page describes how to configure the maximum commit (write) delay time tooptimize write throughput in Spanner.
Overview
To ensure data consistency, Spanner sends write requests toall voting replicas in the database. This replication process can havecomputational overhead. For more information, seeReplication.
Throughput optimized writes provide the option to amortize these computationcosts by executing a group of writes together. To do this,Spanner introduces a small delay and collects a group of writesthat need to be sent to the same voting participants. Executing writes in thisway can provide substantial throughput improvements at the cost of slightlyincreased latency.
Default behavior
If you don't set a commit delay time, Spanner might set a smalldelay for you if it thinks that will amortize the cost of your writes.
Common use cases
You can manually set the delay time of your write requests depending on yourapplication needs. You can also disable commit delays for applications that arehighly latency sensitive by setting the maximum commit delay time to 0 ms.
If you have a latency tolerant application and want to optimize throughput,setting a longer commit delay time significantly improves throughput whileincurring higher latency for each write. For example, if you are bulk loading alarge amount of data and the application doesn't care about how quicklySpanner writes any individual data, then you can set the commitdelay time to a longer value like 100 ms. We recommend that you start with avalue of 100 ms, and then adjust up and down until the latency and throughput tradeoffs satisfy your needs. For most applications, a value between 20 ms and100 ms works best.
If you have a latency sensitive application, Spanner's is alsolatency sensitive by default. If you have a spiky workload,Spanner may set a small delay. You can experiment with setting avalue of 0 ms to determine if the reduced latency at the cost of increasedthroughput is reasonable for your application.
Set mixed commit delay times
You can configure different max commit delay times on subsets of your writes.If you do this, Spanner uses the shortest delay time configuredfor the set of writes. However, we recommend picking a single value for most usecases as this results in more predictable behavior.
Limitations
You can set a commit delay time between 0 and 500 ms. Setting commit delayshigher than 500 ms results in an error.
Set max commit delay on commit requests
The max commit delay parameter is part of theCommitRequest method. You can accessthis method with theRPC API,REST API,or using the Cloud Spanner client library.
C#
usingGoogle.Cloud.Spanner.Data;usingSystem;usingSystem.Threading.Tasks;publicclassCommitDelayAsyncSample{publicasyncTask<int>CommitDelayAsync(stringprojectId,stringinstanceId,stringdatabaseId){stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";usingvarconnection=newSpannerConnection(connectionString);awaitconnection.OpenAsync();returnawaitconnection.RunWithRetriableTransactionAsync(asynctransaction=>{transaction.TransactionOptions.MaxCommitDelay=TimeSpan.FromMilliseconds(100);usingvarinsertSingerCmd=connection.CreateInsertCommand("Singers",newSpannerParameterCollection{{"SingerId",SpannerDbType.Int64,1},{"FirstName",SpannerDbType.String,"Marc"},{"LastName",SpannerDbType.String,"Richards"}});insertSingerCmd.Transaction=transaction;introwsInserted=awaitinsertSingerCmd.ExecuteNonQueryAsync();usingvarinsertAlbumCmd=connection.CreateInsertCommand("Albums",newSpannerParameterCollection{{"SingerId",SpannerDbType.Int64,1},{"AlbumId",SpannerDbType.Int64,2},{"AlbumTitle",SpannerDbType.String,"Go, Go, Go"}});insertAlbumCmd.Transaction=transaction;rowsInserted+=awaitinsertAlbumCmd.ExecuteNonQueryAsync();returnrowsInserted;});}}Go
import("context""fmt""io""time""cloud.google.com/go/spanner")funcsetMaxCommitDelay(wio.Writer,dbstring)error{// db is the fully-qualified database name of the form `projects/<project>/instances/<instance-id>/database/<database-id>`ctx:=context.Background()client,err:=spanner.NewClient(ctx,db)iferr!=nil{returnfmt.Errorf("setMaxCommitDelay.NewClient: %w",err)}deferclient.Close()commitDelay:=100*time.Millisecondresp,err:=client.ReadWriteTransactionWithOptions(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{stmt:=spanner.Statement{SQL:`INSERT Singers (SingerId, FirstName, LastName)VALUES (111, 'Virginia', 'Watson')`,}rowCount,err:=txn.Update(ctx,stmt)iferr!=nil{returnerr}fmt.Fprintf(w,"%d record(s) inserted.\n",rowCount)returnnil},spanner.TransactionOptions{CommitOptions:spanner.CommitOptions{MaxCommitDelay:&commitDelay,ReturnCommitStats:true}})iferr!=nil{returnfmt.Errorf("setMaxCommitDelay.ReadWriteTransactionWithOptions: %w",err)}fmt.Fprintf(w,"%d mutations in transaction\n",resp.CommitStats.MutationCount)returnnil}Java
importcom.google.cloud.spanner.CommitResponse;importcom.google.cloud.spanner.DatabaseClient;importcom.google.cloud.spanner.DatabaseId;importcom.google.cloud.spanner.Mutation;importcom.google.cloud.spanner.Options;importcom.google.cloud.spanner.Spanner;importcom.google.cloud.spanner.SpannerOptions;importjava.time.Duration;importjava.util.Arrays;publicclassSetMaxCommitDelaySample{staticvoidsetMaxCommitDelay(){// TODO(developer): Replace these variables before running the sample.finalStringprojectId="my-project";finalStringinstanceId="my-instance";finalStringdatabaseId="my-database";try(Spannerspanner=SpannerOptions.newBuilder().setProjectId(projectId).build().getService()){finalDatabaseClientdatabaseClient=spanner.getDatabaseClient(DatabaseId.of(projectId,instanceId,databaseId));setMaxCommitDelay(databaseClient);}}staticvoidsetMaxCommitDelay(DatabaseClientdatabaseClient){finalCommitResponsecommitResponse=databaseClient.writeWithOptions(Arrays.asList(Mutation.newInsertOrUpdateBuilder("Albums").set("SingerId").to("1").set("AlbumId").to("1").set("MarketingBudget").to("200000").build(),Mutation.newInsertOrUpdateBuilder("Albums").set("SingerId").to("2").set("AlbumId").to("2").set("MarketingBudget").to("400000").build()),Options.maxCommitDelay(Duration.ofMillis(100)));System.out.println("Updated data with timestamp + "+commitResponse.getCommitTimestamp()+".");}}Node.js
const{Spanner,protos}=require('@google-cloud/spanner');/** * TODO(developer): Uncomment the following lines before running the sample. */// const projectId = 'my-project-id';// const instanceId = 'my-instance';// const databaseId = 'my-database';// Creates a client.constspanner=newSpanner({projectId:projectId,});asyncfunctionsetMaxCommitDelay(){constinstance=spanner.instance(instanceId);constdatabase=instance.database(databaseId);database.runTransaction(async(err,transaction)=>{if(err){console.error(err);return;}try{const[rowCount]=awaittransaction.runUpdate({sql:'INSERT Singers (SingerId, FirstName, LastName) VALUES (111, @firstName, @lastName)',params:{firstName:'Virginia',lastName:'Watson',},});console.log(`Successfully inserted${rowCount} record into the Singers table.`,);awaittransaction.commit({maxCommitDelay:protos.google.protobuf.Duration({seconds:0,// 0 secondsnanos:100000000,// 100 milliseconds}),});}catch(err){console.error('ERROR:',err);}finally{// Close the database when finished.database.close();}});}setMaxCommitDelay();Python
# instance_id = "your-spanner-instance"# database_id = "your-spanner-db-id"spanner_client=spanner.Client()instance=spanner_client.instance(instance_id)database=instance.database(database_id)definsert_singers(transaction):row_ct=transaction.execute_update("INSERT Singers (SingerId, FirstName, LastName) "" VALUES (111, 'Grace', 'Bennis')")print("{} record(s) inserted.".format(row_ct))database.run_in_transaction(insert_singers,max_commit_delay=datetime.timedelta(milliseconds=100))Ruby
require"google/cloud/spanner"### This is a snippet for showcasing how to pass max_commit_delay in commit_options.## @param project_id [String] The ID of the Google Cloud project.# @param instance_id [String] The ID of the spanner instance.# @param database_id [String] The ID of the database.#defspanner_set_max_commit_delayproject_id:,instance_id:,database_id:# Instantiates a clientspanner=Google::Cloud::Spanner.newproject:project_idclient=spanner.clientinstance_id,database_idrecords=[{SingerId:1,AlbumId:1,MarketingBudget:200_000},{SingerId:2,AlbumId:2,MarketingBudget:400_000}]# max_commit_delay is the amount of latency in millisecond, this request# is willing to incur in order to improve throughput.# The commit delay must be at least 0ms and at most 500ms.# Default value is nil.commit_options={return_commit_stats:true,max_commit_delay:100}resp=client.upsert"Albums",records,commit_options:commit_optionsputs"Updated data with#{resp.stats.mutation_count} mutations."endMonitor write request latency
You can monitor Spanner CPU utilization and latency using theGoogle Cloud console. When you set a longer delay time for your write requests,expect to seeCPU utilization potentiallydecrease, while latency increases. To learn about latency inSpanner requests, seeCapture and visualize Spanner API request latency.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-15 UTC.