---
title: Write Throughput
---

These actions can improve the throughput of `INSERT`/`UPDATE`/`COPY` statements to the BM25 index.

## Move Merging to the Background

During every `INSERT`/`UPDATE`/`COPY`/`VACUUM`, the BM25 index runs a compaction process that looks for opportunities to merge [segments](/documentation/concepts/index#segment)
together. The goal is to consolidate smaller segments into larger ones, reducing the total number of segments and improving query performance.

Segments become candidates for merging if their combined size meets or exceeds one of several **configurable layer thresholds**. These thresholds define target
segment sizes — such as `10KB`, `100KB`, `1MB`, etc. For each layer, the compactor checks if there are enough smaller segments whose total size adds up to the threshold.

By default, layer sizes `1KB`, `10KB`, `100KB` and `1MB` are merged in the foreground, while layer sizes `10MB`, `100MB`, `1GB`, `10GB`, `100GB`, and `1TB`
are merged in the background. `layer_sizes` configures the foreground layers, while `background_layer_sizes` configures the background layers.

```sql
-- Set the layer sizes at CREATE INDEX time
CREATE INDEX search_idx ON mock_items USING bm25 (id, description, rating) WITH (key_field = 'id', background_layer_sizes = '100MB, 1GB');

-- Change the layer sizes
ALTER INDEX search_idx SET (background_layer_sizes = '100MB, 1GB');
```

Setting `background_layer_sizes` to `0` disables background merging, and setting `layer_sizes` to `0` disables foreground merging.

```sql
ALTER INDEX search_idx SET (layer_sizes = '0');
```

As a general rule of thumb, merging more layers in the background improves write throughput, since it is non-blocking. For instance,
the following command moves all merging to the background.

```sql
ALTER INDEX search_idx SET (layer_sizes = '0', background_layer_sizes = '100kb, 1mb, 100mb');
```

## Increase Work Memory for Bulk Updates

`work_mem` controls how much memory to allocate to a single `INSERT`/`UPDATE`/`COPY` statement. Each statement that writes to a BM25 index is required to have at least `15MB` memory. If
`work_mem` is below `15MB`, it will be ignored and `15MB` will be used.

If your typical update patterns are large, bulk updates (not single-row updates) a larger value may be better.

```sql
SET work_mem = 64MB;
```

Since many write operations can be running concurrently, this value should be raised more conservatively than `maintenance_work_mem`.

## Enable Mutable Segments

The `mutable_segment_rows` setting enables use of mutable segments, which buffer the rows written to the index in order to amortize the cost of indexing them.

```sql
ALTER INDEX search_idx SET (mutable_segment_rows = 1000);
```

Setting `mutable_segment_rows` to a value greater than 0 will cause that many rows to be cheaply buffered at write time, and to instead be
indexed at read time (i.e. during `SELECT` statements). This can significantly increase the number of writes that an index can sustain,
at the cost of a proportional decrease in read throughput.

<Note>
  The content of mutable segments are indexed and held in memory at read time,
  so large `mutable_segment_rows` values are not advised.
</Note>
