Skip to content

Batching

Each call to AssertAsync or PatchAsync on KindHandle<T> buffers the operation and flushes it to the server immediately. For bulk writes, this means one TCP write per entity. Batching lets you buffer many operations and flush them all at once.

When writing many entities of the same kind, use handle.Batch():

await using var batch = players.Batch();
foreach (var player in updatedPlayers)
{
await batch.AssertAsync(player);
}
// All writes are flushed here when the batch is disposed.

The batch buffers all operations in memory and flushes them in a single TCP write when the batch is disposed (at the end of the await using block).

To write across multiple entity kinds in one flush, use client.Batch():

await using var batch = client.Batch();
await batch.AssertAsync(players, alice);
await batch.AssertAsync(players, bob);
await batch.AssertAsync(inventory, aliceInventory);
// All writes across both kinds are flushed together on dispose.
ScenarioRecommendation
Single entity writeUse handle.AssertAsync() directly. Batching adds no benefit.
Loop over 10+ entities of the same kindUse handle.Batch(). Reduces TCP writes from N to 1.
Writing to multiple kinds in a single logical operationUse client.Batch(). All writes flush together.
Source epoch re-assertionAlways batch. Re-asserting an entire snapshot is the primary use case for batching. See Source Epochs.

Client-side batching and server-side coalescing are complementary:

  • Batching reduces the number of TCP writes (network efficiency).
  • Coalescing merges operations on the same entity within a time window (disk and notification efficiency).

A batch of 1,000 writes arrives at the server as a single TCP payload. The server’s accumulator marks all affected entities as dirty. At the end of the coalescing window, only the net result for each entity is flushed.