From a3e6fe0c0d5b366673e594369f934751516bd57a Mon Sep 17 00:00:00 2001 From: Marc Selwan Date: Tue, 23 Sep 2025 12:30:37 -0700 Subject: [PATCH 1/4] Adds compaction to R2 Data Catalog docs and wrangler commands --- .../docs/r2/data-catalog/about-compaction.mdx | 45 +++++++++++ .../docs/r2/data-catalog/manage-catalogs.mdx | 77 +++++++++++++++++-- .../partials/workers/wrangler-commands/r2.mdx | 34 ++++++++ 3 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 src/content/docs/r2/data-catalog/about-compaction.mdx diff --git a/src/content/docs/r2/data-catalog/about-compaction.mdx b/src/content/docs/r2/data-catalog/about-compaction.mdx new file mode 100644 index 000000000000000..6e707f5392f9a0f --- /dev/null +++ b/src/content/docs/r2/data-catalog/about-compaction.mdx @@ -0,0 +1,45 @@ +--- +pcx_content_type: configuration +title: About compaction +description: Learn about R2 Data Catalog compaction +sidebar: + order: 4 +--- + +## What is compaction? + +Compaction is the process of taking a group of small files and combining them into fewer larger files. This is an important maintenance operation as it helps ensure that performance remains consistent by reducing the number of files that needs to be scanned. + +## Why do I need compaction? + +Every write operation in Apache Iceberg, no matter how small or large, results in a series of new files being generated. As time goes on, the number of files can grow unbounded. This can lead to: +- Increased metadata overhead: Each file has its own metadata, file path, column statistics, etc. This means the query engine will have to read a large amount of metadata to satisfy a given query. +- Increased I/O operations: Without compaction, query engines will have to open and read each individual file, resulting in increased resource usage and cost. +- Reduced compression efficiency: Smaller files tend to compress less efficiently compared to larger files. + +## R2 Data Catalog Compaction + +R2 Data Catalog can now [manage compaction](/r2/data-catalog/manage-catalogs) for Apache Iceberg tables stored in R2. The compaction service periodically runs every hour and compacts new files that have not been compacted yet. + +You can tell which files in R2 have been compacted as they have a `compacted-` added to the file name in the `/data/` directory. + +### Choosing the right target file size + +You can configure the target file size compaction should try to generate if possible. There is a minimum of `64 MB` and a maximum of `512 MB` currently. + +Different compute engines tend to have different best practices when it comes to ideal file sizes so it's best to consult their documentation to find out what's best. + +It's important to note that there are performance tradeoffs to keep in mind based on the use case. For example, if your use case is primarily performing queries that are well defined and will return small amounts of data, having a smaller target file size might be more beneficial as you might end up reading more data than necessary with larger files. +- For workloads that are more latency sensitive, consider a smaller target file size (for example, 64MB - 128MB) +- For streaming ingest workloads, consider medium file sizes (for example, 128MB - 256MB) +- For OLAP style queries that need to scan a lot of data, consider larger file sizes (for example, 256MB - 512MB) + +:::note +Make sure to check to your compute engine documentation to check if there's a recommended file size. +::: + +## Current limitations +- During open beta, compaction will compact up to 2GB worth of files once per hour for each table. +- Only data files stored in parquet format are currently supported with compaction. +- Snapshot expiration and orphan file cleanup is not supported yet. +- Minimum target file size is 64 MB and maximum is 512 MB. diff --git a/src/content/docs/r2/data-catalog/manage-catalogs.mdx b/src/content/docs/r2/data-catalog/manage-catalogs.mdx index 1f9c4c576dbbbea..e69ffaa618979d2 100644 --- a/src/content/docs/r2/data-catalog/manage-catalogs.mdx +++ b/src/content/docs/r2/data-catalog/manage-catalogs.mdx @@ -28,7 +28,8 @@ Learn how to: Enabling the catalog on a bucket turns on the REST catalog interface and provides a **Catalog URI** and **Warehouse name** required by Iceberg clients. Once enabled, you can create and manage Iceberg tables in that bucket. -### Dashboard + + 1. In the Cloudflare dashboard, go to the **R2 object storage** page. @@ -39,8 +40,8 @@ Enabling the catalog on a bucket turns on the REST catalog interface and provide 4. Once enabled, note the **Catalog URI** and **Warehouse name**. -### Wrangler CLI - + + To enable the catalog on your bucket, run the [`r2 bucket catalog enable command`](/workers/wrangler/commands/#r2-bucket-catalog-enable): ```bash @@ -48,13 +49,16 @@ npx wrangler r2 bucket catalog enable ``` After enabling, Wrangler will return your catalog URI and warehouse name. + + + ## Disable R2 Data Catalog on a bucket When you disable the catalog on a bucket, it immediately stops serving requests from the catalog interface. Any Iceberg table references stored in that catalog become inaccessible until you re-enable it. -### Dashboard - + + 1. In the Cloudflare dashboard, go to the **R2 object storage** page. @@ -63,13 +67,72 @@ When you disable the catalog on a bucket, it immediately stops serving requests 3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and select **Disable**. -### Wrangler CLI - + + To disable the catalog on your bucket, run the [`r2 bucket catalog disable command`](/workers/wrangler/commands/#r2-bucket-catalog-disable): ```bash npx wrangler r2 bucket catalog disable ``` + + + +## Enable compaction +Compaction is a performance optimization that takes the many small files created when ingesting data and combines them into fewer, larger files according to the set `target file size`. [Click here](http:///r2/data-catalog/about-compaction) to learn more about compaction. + + + + +1. In the Cloudflare dashboard, go to the **R2 object storage** page. + + +2. Select the bucket you want to enable compaction on. +3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **edit** icon next to the compaction card. +4. Click enable and optionally set a target file size. The default is 128MB. +5. Provide a credential: you can choose to allow us generate an account-level token on your behalf, which is scoped to your bucket (recommended); or, you can manually input a token. +6. Slick *save* + + + + + +To enable the compaction on your catalog, run the [`r2 bucket catalog enable command`](/workers/wrangler/commands/#r2-bucket-catalog-compaction-enable): + +```bash +npx wrangler r2 bucket catalog compaction enable --targetSizeMb 128 --token +``` + + +An API Token is a required argument to enable compaction because our process needs to access and write metadata in R2 Catalog and access files in the R2 bucket, just like any Iceberg client would require. So we need an API Token with R2 Bucket Read/Write permissions and R2 Catalog Read/Write permissions. The token is encrypted and securely accessed only by our compaction processor. Once saved, it is not required again if you re-enable compaction on your Catalog after disabling it. + +After enabling, compaction will be enabled retroactively on all existing tables, and will be enabled by default for newly created tables. During open beta, we currently compact up to 2GB worth of files once per hour for each table. + +## Disable compaction +Disabling compaction will prevent the process from running for all tables within the Catalog. You can re-enable it at any time. + + + + + +1. In the Cloudflare dashboard, go to the **R2 object storage** page. + + +2. Select the bucket you want to enable compaction on. +3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **edit** icon next to the compaction card. +4. Click **disable**. +5. Slick *save*. + + + + + +To disable the compaction on your catalog, run the [`r2 bucket catalog disable command`](/workers/wrangler/commands/#r2-bucket-catalog-compaction-disable): + +```bash +npx wrangler r2 bucket catalog compaction disable --token +``` + + ## Authenticate your Iceberg engine diff --git a/src/content/partials/workers/wrangler-commands/r2.mdx b/src/content/partials/workers/wrangler-commands/r2.mdx index 9ceb5b01bf7dad7..06c84c5100bffc2 100644 --- a/src/content/partials/workers/wrangler-commands/r2.mdx +++ b/src/content/partials/workers/wrangler-commands/r2.mdx @@ -106,6 +106,40 @@ wrangler r2 bucket catalog get [OPTIONS] - `NAME` - The name of the R2 bucket whose data catalog status to retrieve. + + +Enable compaction on a [R2 Data Catalog](/r2/data-catalog/). + +```txt +wrangler r2 bucket catalog compaction enable [OPTIONS] +``` + +- `BUCKET` + - The name of the bucket to enable R2 Data Catalog compaction for. +- `--token` + - The R2 API token with R2 Data Catalog edit permissions +- `--targetSizeMb` + - The target file size compaction will attempt to generate if possible. Default: 128MB. + + + +Disable compaction on a [R2 Data Catalog](/r2/data-catalog/). + +```txt +wrangler r2 bucket catalog compaction disable [OPTIONS] +``` + +- `BUCKET` + - The name of the bucket to enable R2 Data Catalog compaction for. + Set the [CORS configuration](/r2/buckets/cors/) for an R2 bucket from a JSON file. From 2babf07aad3eb60dd22db24067ab632d31339ec9 Mon Sep 17 00:00:00 2001 From: Marc Selwan Date: Tue, 23 Sep 2025 14:47:49 -0700 Subject: [PATCH 2/4] adding changelog for compaction in the PR due to deep linking to new doc pages in this repo --- src/assets/images/changelog/r2/compaction.png | Bin 0 -> 48793 bytes .../r2/2025-09-25-data-catalog-compaction.mdx | 39 ++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/assets/images/changelog/r2/compaction.png create mode 100644 src/content/changelog/r2/2025-09-25-data-catalog-compaction.mdx diff --git a/src/assets/images/changelog/r2/compaction.png b/src/assets/images/changelog/r2/compaction.png new file mode 100644 index 0000000000000000000000000000000000000000..a593507c0349f0cc4b37b13cfb3a268ec5f7f046 GIT binary patch literal 48793 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 --targetSizeMb 128 --token +``` + +And that's it. Compaction will start running automatically. + + + + \ No newline at end of file From aa90ed074706521849445b252812bf17cea8c86c Mon Sep 17 00:00:00 2001 From: Phillip Jones Date: Tue, 23 Sep 2025 18:37:28 -0700 Subject: [PATCH 3/4] Mostly small changes to compaction docs + changelog --- .../r2/2025-09-25-data-catalog-compaction.mdx | 28 ++++++------------- .../docs/r2/data-catalog/about-compaction.mdx | 26 ++++++++--------- .../r2/data-catalog/config-examples/index.mdx | 2 +- .../docs/r2/data-catalog/manage-catalogs.mdx | 24 ++++++++-------- .../partials/workers/wrangler-commands/r2.mdx | 4 +-- 5 files changed, 34 insertions(+), 50 deletions(-) diff --git a/src/content/changelog/r2/2025-09-25-data-catalog-compaction.mdx b/src/content/changelog/r2/2025-09-25-data-catalog-compaction.mdx index 6395fccc1291b40..dc6ba4dcaae00f9 100644 --- a/src/content/changelog/r2/2025-09-25-data-catalog-compaction.mdx +++ b/src/content/changelog/r2/2025-09-25-data-catalog-compaction.mdx @@ -1,39 +1,27 @@ --- -title: R2 Data Catalog now supports compaction. +title: R2 Data Catalog now supports compaction description: Users can now enable compaction on R2 Data Catalog products: - r2 -date: 2025-09-25 +date: 2025-09-25T13:00:00 hidden: true --- import { LinkCard, } from "~/components"; -Today, we're adding support for managed [compaction](/r2/data-catalog/about-compaction) for [Apache Iceberg](https://iceberg.apache.org/) tables managed by [R2 Data Catalog](/r2/data-catalog/). +You can now enable automatic compaction for [Apache Iceberg](https://iceberg.apache.org/) tables in [R2 Data Catalog](/r2/data-catalog/) to improve query performance. -Compaction is the process of taking a group of small files and combining them into fewer larger files. This is an important maintenance operation as it helps ensure that performance remains consistent by reducing the number of files that needs to be scanned when running queries. +Compaction is the process of taking a group of small files and combining them into fewer larger files. This is an important maintenance operation as it helps ensure that query performance remains consistent by reducing the number of files that needs to be scanned. -To enable compaction in R2 Data Catalog, find it under **R2 Data Catalog** in your bucket settings in the dashboard +To enable automatic compaction in R2 Data Catalog, find it under **R2 Data Catalog** in your R2 bucket settings in the dashboard. ![compaction-dash](~/assets/images/changelog/r2/compaction.png) -or simply run: +Or with [Wrangler](/workers/wrangler/), run: ```bash -npx wrangler r2 bucket catalog compaction enable --targetSizeMb 128 --token +npx wrangler r2 bucket catalog compaction enable --target-size 128 --token ``` -And that's it. Compaction will start running automatically. - - - - \ No newline at end of file +To get started with compaction, check out [manage catalogs](/r2/data-catalog/manage-catalogs/). For best practices and limitations, refer to [about compaction](/r2/data-catalog/about-compaction/). \ No newline at end of file diff --git a/src/content/docs/r2/data-catalog/about-compaction.mdx b/src/content/docs/r2/data-catalog/about-compaction.mdx index 6e707f5392f9a0f..6f9ad6417473a87 100644 --- a/src/content/docs/r2/data-catalog/about-compaction.mdx +++ b/src/content/docs/r2/data-catalog/about-compaction.mdx @@ -8,36 +8,32 @@ sidebar: ## What is compaction? -Compaction is the process of taking a group of small files and combining them into fewer larger files. This is an important maintenance operation as it helps ensure that performance remains consistent by reducing the number of files that needs to be scanned. +Compaction is the process of taking a group of small files and combining them into fewer larger files. This is an important maintenance operation as it helps ensure that query performance remains consistent by reducing the number of files that needs to be scanned. ## Why do I need compaction? -Every write operation in Apache Iceberg, no matter how small or large, results in a series of new files being generated. As time goes on, the number of files can grow unbounded. This can lead to: -- Increased metadata overhead: Each file has its own metadata, file path, column statistics, etc. This means the query engine will have to read a large amount of metadata to satisfy a given query. -- Increased I/O operations: Without compaction, query engines will have to open and read each individual file, resulting in increased resource usage and cost. -- Reduced compression efficiency: Smaller files tend to compress less efficiently compared to larger files. +Every write operation in [Apache Iceberg](https://iceberg.apache.org/), no matter how small or large, results in a series of new files being generated. As time goes on, the number of files can grow unbounded. This can lead to: +- Slower queries and increased I/O operations: Without compaction, query engines will have to open and read each individual file, resulting in longer query times and increased costs. +- Increased metadata overhead: Query engines must scan metadata files to determine which ones to read. With thousands of small files, query planning takes longer even before data is accessed. +- Reduced compression efficiency: Smaller files compress less efficiently than larger files, leading to higher storage costs and more data to transfer during queries. -## R2 Data Catalog Compaction +## R2 Data Catalog automatic compaction -R2 Data Catalog can now [manage compaction](/r2/data-catalog/manage-catalogs) for Apache Iceberg tables stored in R2. The compaction service periodically runs every hour and compacts new files that have not been compacted yet. +R2 Data Catalog can now [manage compaction](/r2/data-catalog/manage-catalogs) for Apache Iceberg tables stored in R2. When enabled, compaction runs automatically and combines new files that have not been compacted yet. -You can tell which files in R2 have been compacted as they have a `compacted-` added to the file name in the `/data/` directory. +Compacted files are prefixed with `compacted-` in the `/data/` directory. ### Choosing the right target file size -You can configure the target file size compaction should try to generate if possible. There is a minimum of `64 MB` and a maximum of `512 MB` currently. +You can configure the target file size for compaction. Currently, the minimum is 64 MB and the maximum is 512 MB. -Different compute engines tend to have different best practices when it comes to ideal file sizes so it's best to consult their documentation to find out what's best. +Different compute engines have different optimal file sizes, so check their documentation. -It's important to note that there are performance tradeoffs to keep in mind based on the use case. For example, if your use case is primarily performing queries that are well defined and will return small amounts of data, having a smaller target file size might be more beneficial as you might end up reading more data than necessary with larger files. +Performance tradeoffs depend on your use case. For example, queries that return small amounts of data may perform better with smaller files, as larger files could result in reading unnecessary data. - For workloads that are more latency sensitive, consider a smaller target file size (for example, 64MB - 128MB) - For streaming ingest workloads, consider medium file sizes (for example, 128MB - 256MB) - For OLAP style queries that need to scan a lot of data, consider larger file sizes (for example, 256MB - 512MB) -:::note -Make sure to check to your compute engine documentation to check if there's a recommended file size. -::: - ## Current limitations - During open beta, compaction will compact up to 2GB worth of files once per hour for each table. - Only data files stored in parquet format are currently supported with compaction. diff --git a/src/content/docs/r2/data-catalog/config-examples/index.mdx b/src/content/docs/r2/data-catalog/config-examples/index.mdx index d0d4e7ea80b71ca..0010b7a970d64c8 100644 --- a/src/content/docs/r2/data-catalog/config-examples/index.mdx +++ b/src/content/docs/r2/data-catalog/config-examples/index.mdx @@ -3,7 +3,7 @@ pcx_content_type: navigation title: Connect to Iceberg engines head: [] sidebar: - order: 4 + order: 5 group: hideIndex: true description: Find detailed setup instructions for Apache Spark and other common query engines. diff --git a/src/content/docs/r2/data-catalog/manage-catalogs.mdx b/src/content/docs/r2/data-catalog/manage-catalogs.mdx index e69ffaa618979d2..5af7d14231ead8d 100644 --- a/src/content/docs/r2/data-catalog/manage-catalogs.mdx +++ b/src/content/docs/r2/data-catalog/manage-catalogs.mdx @@ -78,7 +78,7 @@ npx wrangler r2 bucket catalog disable ## Enable compaction -Compaction is a performance optimization that takes the many small files created when ingesting data and combines them into fewer, larger files according to the set `target file size`. [Click here](http:///r2/data-catalog/about-compaction) to learn more about compaction. +Compaction improves query performance by combining the many small files created during data ingestion into fewer, larger files according to the set `target file size`. For more information about compaction and why it's valuable, refer to [About compaction](/r2/data-catalog/about-compaction/). @@ -87,10 +87,10 @@ Compaction is a performance optimization that takes the many small files created 2. Select the bucket you want to enable compaction on. -3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **edit** icon next to the compaction card. -4. Click enable and optionally set a target file size. The default is 128MB. -5. Provide a credential: you can choose to allow us generate an account-level token on your behalf, which is scoped to your bucket (recommended); or, you can manually input a token. -6. Slick *save* +3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **Edit** icon next to the compaction card. +4. Enable compaction and optionally set a target file size. The default is 128MB. +5. (Optional) Provide a Cloudflare API token for compaction to access and rewrite files in your bucket. +6. Select **Save**. @@ -99,16 +99,16 @@ Compaction is a performance optimization that takes the many small files created To enable the compaction on your catalog, run the [`r2 bucket catalog enable command`](/workers/wrangler/commands/#r2-bucket-catalog-compaction-enable): ```bash -npx wrangler r2 bucket catalog compaction enable --targetSizeMb 128 --token +npx wrangler r2 bucket catalog compaction enable --target-size 128 --token ``` -An API Token is a required argument to enable compaction because our process needs to access and write metadata in R2 Catalog and access files in the R2 bucket, just like any Iceberg client would require. So we need an API Token with R2 Bucket Read/Write permissions and R2 Catalog Read/Write permissions. The token is encrypted and securely accessed only by our compaction processor. Once saved, it is not required again if you re-enable compaction on your Catalog after disabling it. +Compaction requires a Cloudflare API token with **both** R2 storage and R2 Data Catalog read/write permissions to act as a service credential. The compaction process uses this token to read files, combine them, and update table metadata. Refer to [Authenticate your Iceberg engine](#authenticate-your-iceberg-engine) for details on creating a token with the required permissions. -After enabling, compaction will be enabled retroactively on all existing tables, and will be enabled by default for newly created tables. During open beta, we currently compact up to 2GB worth of files once per hour for each table. +Once enabled, compaction applies retroactively to all existing tables and automatically to newly created tables. During open beta, we currently compact up to 2GB worth of files once per hour for each table. ## Disable compaction -Disabling compaction will prevent the process from running for all tables within the Catalog. You can re-enable it at any time. +Disabling compaction will prevent the process from running for all tables managed by the catalog. You can re-enable it at any time. @@ -119,8 +119,8 @@ Disabling compaction will prevent the process from running for all tables within 2. Select the bucket you want to enable compaction on. 3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **edit** icon next to the compaction card. -4. Click **disable**. -5. Slick *save*. +4. Disable compaction. +5. Select **Save**. @@ -129,7 +129,7 @@ Disabling compaction will prevent the process from running for all tables within To disable the compaction on your catalog, run the [`r2 bucket catalog disable command`](/workers/wrangler/commands/#r2-bucket-catalog-compaction-disable): ```bash -npx wrangler r2 bucket catalog compaction disable --token +npx wrangler r2 bucket catalog compaction disable ``` diff --git a/src/content/partials/workers/wrangler-commands/r2.mdx b/src/content/partials/workers/wrangler-commands/r2.mdx index 06c84c5100bffc2..63b9661e3db0115 100644 --- a/src/content/partials/workers/wrangler-commands/r2.mdx +++ b/src/content/partials/workers/wrangler-commands/r2.mdx @@ -122,8 +122,8 @@ wrangler r2 bucket catalog compaction enable [OPTIONS] - The name of the bucket to enable R2 Data Catalog compaction for. - `--token` - The R2 API token with R2 Data Catalog edit permissions -- `--targetSizeMb` - - The target file size compaction will attempt to generate if possible. Default: 128MB. +- `--target-size` + - The target file size (in MB) compaction will attempt to generate. Default: 128. Date: Wed, 24 Sep 2025 09:22:59 +0100 Subject: [PATCH 4/4] PCX Review --- src/content/docs/r2/data-catalog/about-compaction.mdx | 8 ++++---- src/content/docs/r2/data-catalog/manage-catalogs.mdx | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/content/docs/r2/data-catalog/about-compaction.mdx b/src/content/docs/r2/data-catalog/about-compaction.mdx index 6f9ad6417473a87..32ff9d45c73af24 100644 --- a/src/content/docs/r2/data-catalog/about-compaction.mdx +++ b/src/content/docs/r2/data-catalog/about-compaction.mdx @@ -30,12 +30,12 @@ You can configure the target file size for compaction. Currently, the minimum is Different compute engines have different optimal file sizes, so check their documentation. Performance tradeoffs depend on your use case. For example, queries that return small amounts of data may perform better with smaller files, as larger files could result in reading unnecessary data. -- For workloads that are more latency sensitive, consider a smaller target file size (for example, 64MB - 128MB) -- For streaming ingest workloads, consider medium file sizes (for example, 128MB - 256MB) -- For OLAP style queries that need to scan a lot of data, consider larger file sizes (for example, 256MB - 512MB) +- For workloads that are more latency sensitive, consider a smaller target file size (for example, 64 MB - 128 MB) +- For streaming ingest workloads, consider medium file sizes (for example, 128 MB - 256 MB) +- For OLAP style queries that need to scan a lot of data, consider larger file sizes (for example, 256 MB - 512 MB) ## Current limitations -- During open beta, compaction will compact up to 2GB worth of files once per hour for each table. +- During open beta, compaction will compact up to 2 GB worth of files once per hour for each table. - Only data files stored in parquet format are currently supported with compaction. - Snapshot expiration and orphan file cleanup is not supported yet. - Minimum target file size is 64 MB and maximum is 512 MB. diff --git a/src/content/docs/r2/data-catalog/manage-catalogs.mdx b/src/content/docs/r2/data-catalog/manage-catalogs.mdx index 5af7d14231ead8d..ec8642967252688 100644 --- a/src/content/docs/r2/data-catalog/manage-catalogs.mdx +++ b/src/content/docs/r2/data-catalog/manage-catalogs.mdx @@ -88,7 +88,7 @@ Compaction improves query performance by combining the many small files created 2. Select the bucket you want to enable compaction on. 3. Switch to the **Settings** tab, scroll down to **R2 Data Catalog**, and click on the **Edit** icon next to the compaction card. -4. Enable compaction and optionally set a target file size. The default is 128MB. +4. Enable compaction and optionally set a target file size. The default is 128 MB. 5. (Optional) Provide a Cloudflare API token for compaction to access and rewrite files in your bucket. 6. Select **Save**. @@ -103,9 +103,13 @@ npx wrangler r2 bucket catalog compaction enable --target-size 12 ``` -Compaction requires a Cloudflare API token with **both** R2 storage and R2 Data Catalog read/write permissions to act as a service credential. The compaction process uses this token to read files, combine them, and update table metadata. Refer to [Authenticate your Iceberg engine](#authenticate-your-iceberg-engine) for details on creating a token with the required permissions. -Once enabled, compaction applies retroactively to all existing tables and automatically to newly created tables. During open beta, we currently compact up to 2GB worth of files once per hour for each table. +:::note[API token permission requirements] +Compaction requires a Cloudflare API token with both R2 storage and R2 Data Catalog read/write permissions to act as a service credential. The compaction process uses this token to read files, combine them, and update table metadata. + +Refer to [Authenticate your Iceberg engine](#authenticate-your-iceberg-engine) for details on creating a token with the required permissions. + +Once enabled, compaction applies retroactively to all existing tables and automatically to newly created tables. During open beta, we currently compact up to 2 GB worth of files once per hour for each table. ## Disable compaction Disabling compaction will prevent the process from running for all tables managed by the catalog. You can re-enable it at any time.