Skip to main content

S3 Tables location

S3 Tables is AWS's managed Apache Iceberg table storage built directly into S3. Use this location type to store Depot Dataset data in an S3 Tables bucket. Athena, DuckDB and Spark reach its datasets directly: see Iceberg interop case studies.

Account prerequisite

The account's bootstrap must be deployed with s3TablesIceberg: true. Without it the environment deploy fails: the stack imports SDP-Bootstrap-S3TablesLfGrantCrRoleArn, an export that only this flag creates.

Configuration properties​

PropertyRequiredDefaultDescription
nameyes—A name or alias for this location. Must be unique within the environment.
tableBucketNamenosdp-${envId}-dataOverride the default table bucket name. Strongly discouraged — AWS allows only 10 table buckets per region per account. Use only if you must point at a pre-existing bucket or share a bucket across environments.
tableBucketArnno—ARN of an externally-provisioned S3 Tables bucket. When set, Depot does not create or manage the bucket lifecycle — it only creates its own Catalog Integration and Linked Catalog Database against the external bucket. Mutually exclusive with tableBucketName.
removalPolicynoRETAINRemoval policy for the bucket that backs this location. One of DESTROY, RETAIN, SNAPSHOT. Use DESTROY for non-production.
icebergVersionno2Iceberg table format version to use for tables created under this location. Accepts 2 or 3. Use 3 only if all consumers (Snowflake, Athena, etc.) support Iceberg v3 in your environment — consult the Iceberg compatibility matrix to verify reader support before opting in. Per-table override: snowflake.iceberg.icebergVersion schema extension.
deleteModenoMERGE_ON_READRow-level delete strategy for Iceberg tables. MERGE_ON_READ writes delete files and lets readers reconcile. COPY_ON_WRITE rewrites data files on every delete or update. Per-table override: snowflake.iceberg.deleteMode schema extension.

Example​

import { Location } from '@stage-tech/depot-cdk';

new Location.S3Tables(this, 'MyDataLake', {
environment,
name: 'my-data-lake',
// icebergVersion: 3,
// deleteMode: 'COPY_ON_WRITE',
});

Supported field types​

Field typeStored as
Every scalarOne typed column
array and set of any scalar or enumARRAY(X); binary and secret elements are base64 VARCHAR
ref in an array or setARRAY(OBJECT(...)) holding the id, plus version when the ref is versioned
struct at any depthTyped columns, or a typed OBJECT(...) for layout: structured
map of scalars, refs, structs, arrays or mapsMAP(VARCHAR, X)
Array of arrays, maps or structsNested ARRAY, MAP and OBJECT types, at any depth
anyJSON text in VARCHAR on Iceberg v2; VARIANT on Iceberg v3

Nested struct keys are stored lower_snake. Map keys are stored as written.

x in <array of arrays> is refused; x in r for any r of <array of arrays> works. On Iceberg v3, Snowflake rejects a NULL element in an array of any.

Refused at planning​

A migration with one of these changes fails when it is planned:

  • switching a struct between layout: flattened and layout: structured;
  • switching a property between an array and an array of arrays;
  • retyping a value out of any, top-level or nested;
  • turning an unversioned ref inside an array, set, map or structured struct into a versioned one: stored refs carry no version and would read back as null.

External bucket mode​

Use tableBucketArn to point Depot at a bucket provisioned and managed outside of Depot (e.g. shared infrastructure or a cross-team bucket).

In external mode Depot:

  • does not create or delete the AWS::S3Tables::TableBucket resource
  • creates its own Snowflake Catalog Integration and Linked Catalog Database against the external bucket
  • does not manage the bucket or namespace lifecycle
new Location.S3Tables(this, 'ExternalLake', {
environment,
name: 'external-lake',
tableBucketArn: 'arn:aws:s3tables:eu-west-1:111122223333:bucket/shared-bucket',
});

Dataset-level namespace management is configured separately on the dataset's s3tables extension. Set namespaceManagement: 'EXTERNAL' there if the namespace itself is also externally managed.

Cross-account external buckets​

When tableBucketArn belongs to a different AWS account, Depot cannot automate Lake Formation setup — the owning account must configure the following manually before Snowflake queries will succeed:

  1. Account-level prerequisites (once per account): an account bootstrapped by Depot with s3TablesIceberg: true already has them. In any other account, register arn:aws:s3tables:{region}:{account}:bucket/* as a Lake Formation data location (WithFederation: true) using a role that trusts lakeformation.amazonaws.com with sts:AssumeRole. Create a Glue federated catalog (s3tablescatalog) pointing to that wildcard ARN.

  2. Catalog-level grant (once per bucket): grant ALL on the default Glue catalog and on the S3 Tables sub-catalog ({ownerAccountId}:s3tablescatalog/{bucketName}) to the Snowflake IAM role.

  3. Namespace-level grant (once per dataset): grant ALL on Database { CatalogId: "{ownerAccountId}:s3tablescatalog/{bucketName}", Name: "{namespaceName}" } to the Snowflake IAM role.

The Snowflake IAM role must also have lakeformation:GetDataAccess in its IAM policy. Cross-account LF grants may additionally require AWS Resource Access Manager (RAM) sharing — consult the AWS Lake Formation cross-account documentation.

Removed in Depot 10.7.0

Before Depot 10.7.0, depot-cdk had a Glue-catalog Location.Iceberg location and an Executor.EmrServerless executor that ran Spark on it. 10.7.0 removed both; S3 Tables replaces them. depot-cdk rejects them at the type level, so upgrading from 10.6.0 may require removing them from the CDK code.