Generated banner for Creating Data Lake Table
Generated logo for Creating Data Lake Table

Creating Data Lake Table

AWSOfficialPublished by AWS

  • Skill
  • Workflow
  • Cloud and DevOps
  • Apache-2.0
  • No issues found

From the author

Create managed Iceberg tables using Amazon S3 Tables (s3tables API namespace) with automatic compaction and snapshot management. Sets up table bucket, namespace, table, schema, Glue catalog registration, partitioning, IAM access control. Triggers on: create table, data lake table, analytics table, structured data storage, S3 Tables, Iceberg, Athena table, partitioning strategy, access permissions. Do NOT use for: importing files (use ingesting-into-data-lake), vector storage (use storing-and-querying-vectors), querying existing tables (use querying-data-lake), or locating existing table (use finding-data-lake-assets).
— the description by AWS

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured workflow for creating and managing Iceberg tables within Amazon S3 Tables. It covers the end-to-end process, including bucket creation, namespace setup, Glue Data Catalog integration, IAM access control, and table schema definition. It ensures that users follow best practices for partitioning and storage management while avoiding common pitfalls like manual location specification or incorrect IAM policy namespaces.

What it does

  • Creates and configures S3 Tables buckets and namespaces.
  • Integrates S3 Tables with the AWS Glue Data Catalog.
  • Defines Iceberg table schemas and partitioning strategies.
  • Configures necessary IAM and bucket policies for secure access.
  • Provides paths for both API-based and Athena DDL-based table creation.
  • Validates table existence and configuration before execution.

When to use it

  • When you need to provision a new managed Iceberg table in Amazon S3 Tables.
  • When setting up structured data storage for analytics workloads.
  • When you need to integrate S3 Tables with Athena or Glue ETL pipelines.
  • When you need to define specific partitioning strategies for performance optimization.

Advantages

  • Automates complex multi-step infrastructure setup.
  • Ensures adherence to AWS best practices for S3 Tables and Iceberg.
  • Reduces configuration errors by validating existing resources first.
  • Provides clear guidance on IAM and Glue catalog prerequisites.

Usage examples

“Create a new S3 Tables Iceberg table named sales_data in the analytics namespace with a monthly partition on order_date.”
The agent will verify the bucket and namespace, define the schema and partition spec, and execute the creation command via the S3 Tables API.
“I need to set up a new analytics table using Athena DDL for my Iceberg data.”
The agent will guide you through the Athena DDL creation path, ensuring the correct execution context is used without specifying a manual location.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/aws/creating-data-lake-table/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip creating-data-lake-table.zip -d .agents/skills

Documentation by AWS

Create Data Lake Tables with Amazon S3 Tables

Overview

Amazon S3 Tables provides managed Iceberg tables with automatic compaction and snapshot management. Queryable via Athena and Iceberg-compatible engines.

Common Tasks

You MUST use AWS MCP server tools when connected, they provide command validation, sandboxed execution, and audit logging. Fall back to AWS CLI if MCP unavailable.

Decision Guide

Before creating, You MUST check what exists:

You MUST run aws glue get-tables --database-name <NAME> when user mentions a database.

What you findAction
Fuzzy database name ("our analytics db")You MUST STOP. Delegate to finding-data-lake-assets to resolve.
Non-S3-Tables table with matching nameYou MUST STOP. Delegate to finding-data-lake-assets. You MUST NOT create until user confirms.
Existing S3 Tables table with matching nameYou MUST check schema match. Reuse if compatible, recreate only if user confirms.
No matching tablesProceed with creation (Steps 1-8).
User explicitly requests new S3 Tables tableSkip checks, proceed with creation.

Creation paths:

  • Existing data in S3: Create empty table (Steps 1-8), then use ingesting-into-data-lake skill.

  • Glue ETL pipeline: Read references/table-creation-glue-etl.md first, then Steps 1-6.

  • Lake Formation access control: Search AWS docs for "S3 Tables integration with Lake Formation".

1. Verify Dependencies

Constraints:

  • You MUST check whether AWS MCP server tools or AWS CLI are available and inform user if missing

  • You MUST confirm target AWS region and verify credentials with aws sts get-caller-identity

2. Understand the Schema
  • Explicit schema: Validate Iceberg types.

  • Loose description: Ask columns, types, grain. Propose and confirm.

  • Existing S3 data: Infer schema from file headers only. Create empty table first, then use ingesting-into-data-lake skill.

Constraints:

  • You MUST read references/best-practices.md for Iceberg type mapping, partitions, and naming.

  • You MUST ask for all required parameters upfront: table name, columns, types, partition strategy. For schema evolution, see references/athena-ddl-path.md.

  • You MUST use all lowercase names -- Glue rejects mixed case with GENERIC_INTERNAL_ERROR. Namespace and table names MUST NOT contain hyphens.

  • You SHOULD suggest partition columns based on access patterns.

3. Create Table Bucket

Names: 3-63 chars, lowercase, numbers, hyphens.

aws s3tables create-table-bucket --name <BUCKET_NAME> --region <REGION>

Capture table-bucket-arn. Encryption (SSE-S3 default, SSE-KMS) and storage class (STANDARD, INTELLIGENT_TIERING) set at creation. See references/best-practices.md.

Constraints:

  • You MUST check existing buckets with aws s3tables list-table-buckets and ask user to select or create new.

  • If using SSE-KMS, KMS key policy MUST allow S3 Tables maintenance service principal to read data. Search AWS docs for "S3 Tables KMS key policy" for required policy.

  • If bucket creation fails, see references/best-practices.md for common errors.

4. Create Namespace
aws s3tables create-namespace --table-bucket-arn <ARN> --namespace <NAMESPACE>

Constraints:

  • You MUST list existing namespaces first and suggest reusing if relevant

  • You MUST use lowercase names with no hyphens

5. Create Glue Data Catalog Integration

Check if s3tablescatalog exists (create once per region per account):

aws glue get-catalog --catalog-id s3tablescatalog

If not found, create (requires glue:CreateCatalog, glue:passConnection):

aws glue create-catalog --name "s3tablescatalog" --catalog-input '{
  "FederatedCatalog": {
    "Identifier": "arn:aws:s3tables:<REGION>:<ACCOUNT_ID>:bucket/*",
    "ConnectionName": "aws:s3tables"
  },
  "CreateDatabaseDefaultPermissions": [{"Principal": {"DataLakePrincipalIdentifier": "IAM_ALLOWED_PRINCIPALS"}, "Permissions": ["ALL"]}],
  "CreateTableDefaultPermissions": [{"Principal": {"DataLakePrincipalIdentifier": "IAM_ALLOWED_PRINCIPALS"}, "Permissions": ["ALL"]}],
  "AllowFullTableExternalDataAccess": "True"
}'

Verify with aws glue get-catalogs --parent-catalog-id s3tablescatalog.

6. Configure Access Control

S3 Tables uses s3tables:* IAM namespace (not s3:*).

Querying principal permissions (bucket policy):

  • s3tables:GetTableBucket, s3tables:GetNamespace, s3tables:GetTable, s3tables:GetTableMetadataLocation, s3tables:GetTableData

Querying principal permissions (IAM policy):

  • glue:GetCatalog, glue:GetDatabase, glue:GetTable

You MUST scope to correct ARN patterns. You MUST read references/access-control.md for exact resource ARNs.

Constraints:

  • You MUST ask user for querying principal ARN

  • You MUST NOT grant broader permissions than necessary

  • You MUST NOT create IAM roles automatically, verify existing and guide user

7. Create the Table
ContextPath
Default (any user)S3 Tables API (below)
User specifically wants SQL DDLAthena DDL (see references/athena-ddl-path.md)
Glue ETL pipelineSpark DDL via --conf job args (not spark.conf.set()). You MUST read references/table-creation-glue-etl.md for the --conf string.

Default: S3 Tables API:

aws s3tables create-table \
  --table-bucket-arn <ARN> \
  --namespace <NAMESPACE> \
  --name <TABLE_NAME> \
  --format ICEBERG \
  --metadata '<METADATA_JSON>'

Metadata JSON MUST nest under "iceberg" key:

{"iceberg":{"schema":{"fields":[
  {"name":"order_date","type":"date","required":true},
  {"name":"customer_id","type":"string","required":true},
  {"name":"amount","type":"double","required":false}
]},
"partitionSpec":{"fields":[
  {"sourceId":1,"fieldId":1000,"transform":"month","name":"order_date_month"}
]}}}

Constraints:

  • partitionSpec.sourceId MUST reference a valid schema field ID

  • For schema evolution after creation, use Athena DDL. See references/athena-ddl-path.md

  • You MUST use schemaV2 for complex types (list, map, struct) with explicit field IDs. See references/best-practices.md.

  • You SHOULD search AWS docs for "IcebergPartitionField S3 Tables" for supported partition transforms

8. Verify and Confirm

You MUST verify with aws s3tables get-table and confirm queryability with DESCRIBE <table_name> via Athena using --query-execution-context '{"Catalog":"s3tablescatalog/<BUCKET_NAME>","Database":"<NAMESPACE>"}'. Do NOT put catalog in SQL. Present summary: bucket ARN, namespace, table, schema, partitions.

Troubleshooting

ErrorCauseFix
"Table location can not be specified"LOCATION in CREATE TABLERemove LOCATION clause. S3 Tables manages storage automatically.
AccessDeniedException with s3:* policyUsing s3:* not s3tables:*S3 Tables uses s3tables:* namespace. Update IAM policy.

Additional Resources

Files

references/table-creation-glue-etl.md

Creating S3 Tables with Spark DDL in Glue ETL

Use when building Glue ETL pipelines that create and write to S3 Tables. Tables created via the S3 Tables API (aws s3tables create-table --metadata) are also readable by Spark.

Critical Requirements

  • Glue 5.1 or higher is required (Spark 3.5.6, Iceberg 1.10.0). Do NOT use Glue 4.0.

  • --datalake-formats iceberg MUST be set as a job argument

  • Table bucket and namespace MUST exist before running the job

Static Config Gotcha (Most Common Failure)

In Glue 5.x, catalog configs are static and MUST go in --conf job arguments. Using spark.conf.set() throws:

AnalysisException: Cannot modify the value of a static config: spark.sql.extensions

Rule: All spark.sql.catalog.* configuration goes in --conf, never in the PySpark script.

Rule: Catalog and database names containing hyphens MUST be backtick-escaped in Spark SQL (e.g., `my-catalog`.`my-db`.my_table). Without backticks, Spark returns INVALID_IDENTIFIER.

Access Methods

MethodAthena/Redshift accessRecommended
Analytics Integration (GlueCatalog)YesYes, if multi-service
REST EndpointNo (Glue-only)Yes, if Glue-only
REST Endpoint (simplest)
spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.<name>.type=rest
spark.sql.catalog.<name>.uri=https://s3tables.<region>.amazonaws.com/iceberg
spark.sql.catalog.<name>.warehouse=<table_bucket_arn>
spark.sql.catalog.<name>.rest.sigv4-enabled=true
spark.sql.catalog.<name>.rest.signing-name=s3tables
spark.sql.catalog.<name>.rest.signing-region=<region>
spark.sql.catalog.<name>.io-impl=org.apache.iceberg.aws.s3.S3FileIO
Analytics Integration (for Athena/Redshift access)
spark.sql.catalog.<name>=org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.<name>.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog
spark.sql.catalog.<name>.glue.id=<account_id>:s3tablescatalog/<table_bucket_name>
spark.sql.catalog.<name>.warehouse=<table_bucket_arn>

The warehouse parameter is required — without it Spark fails with "Cannot derive default warehouse location".

--conf Format Rules

The --conf argument is a single string with space-separated --conf key=value pairs:

"--conf": "spark.sql.catalog.s3tables=org.apache.iceberg.spark.SparkCatalog --conf spark.sql.catalog.s3tables.type=rest --conf ..."

First key-value has no --conf prefix. Use --cli-input-json file://config.json to avoid shell escaping.

Glue Job Config Example (REST Endpoint)

job-config.json:

{
    "Name": "my-etl-job",
    "Role": "arn:aws:iam::<ACCOUNT>:role/<GLUE_ROLE>",
    "Command": {
        "Name": "glueetl",
        "ScriptLocation": "s3://<BUCKET>/scripts/my_etl.py",
        "PythonVersion": "3"
    },
    "DefaultArguments": {
        "--datalake-formats": "iceberg",
        "--conf": "spark.sql.catalog.s3tables=org.apache.iceberg.spark.SparkCatalog --conf spark.sql.catalog.s3tables.type=rest --conf spark.sql.catalog.s3tables.uri=https://s3tables.<REGION>.amazonaws.com/iceberg --conf spark.sql.catalog.s3tables.warehouse=<TABLE_BUCKET_ARN> --conf spark.sql.catalog.s3tables.rest.sigv4-enabled=true --conf spark.sql.catalog.s3tables.rest.signing-name=s3tables --conf spark.sql.catalog.s3tables.rest.signing-region=<REGION> --conf spark.sql.catalog.s3tables.io-impl=org.apache.iceberg.aws.s3.S3FileIO",
        "--catalog_name": "s3tables",
        "--namespace": "<NAMESPACE>",
        "--table_name": "<TABLE_NAME>"
    },
    "GlueVersion": "5.1",
    "NumberOfWorkers": 2,
    "WorkerType": "G.1X"
}

For Analytics Integration, replace the --conf value with: spark.sql.catalog.s3tablescatalog=org.apache.iceberg.spark.SparkCatalog --conf spark.sql.catalog.s3tablescatalog.catalog-impl=org.apache.iceberg.aws.glue.GlueCatalog --conf spark.sql.catalog.s3tablescatalog.glue.id=<ACCOUNT>:s3tablescatalog/<BUCKET_NAME> --conf spark.sql.catalog.s3tablescatalog.warehouse=<TABLE_BUCKET_ARN>

PySpark Script

Catalog config is in --conf, so the script is clean:

import sys
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job

args = getResolvedOptions(sys.argv, ['JOB_NAME', 'catalog_name', 'namespace', 'table_name'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Do NOT call spark.conf.set() for catalog config in Glue 5.x
# catalog_name must match spark.sql.catalog.<name> from --conf

spark.sql(f"""
CREATE TABLE IF NOT EXISTS {args['catalog_name']}.{args['namespace']}.{args['table_name']} (
  col1 STRING,
  col2 INT
)
USING iceberg
PARTITIONED BY (col1)
""")
# No LOCATION clause -- S3 Tables manages storage

job.commit()

IAM Requirements

The Glue service role needs: AWSGlueServiceRole plus s3tables:GetTableBucket, s3tables:GetNamespace, s3tables:ListNamespaces, s3tables:CreateTable, s3tables:GetTable, s3tables:ListTables, s3tables:UpdateTableMetadataLocation, s3tables:GetTableMetadataLocation, s3tables:GetTableData, s3tables:PutTableData, and glue:GetCatalog, glue:GetDatabase, glue:GetTable, glue:passConnection. Table bucket, namespace, and Glue catalog MUST be created before the Glue job runs (Steps 3-5 in SKILL.md). For exact resource ARN scoping, see access-control.md.

Troubleshooting

IssueFix
"Cannot modify static config"Remove spark.conf.set(). Use --conf job argument.
"Access Denied" on S3 TablesCheck Glue role has granular s3tables: permissions. See IAM Requirements above.
Shell escaping breaks --confUse --cli-input-json file://config.json.
Table not visible in AthenaREST endpoint tables aren't in Athena. Use Analytics Integration.
Catalog not foundEnsure catalog name in script matches spark.sql.catalog.<name> from --conf.

Additional Resources

For latest Glue ETL guidance, search AWS docs for "Running ETL jobs on Amazon S3 tables with AWS Glue".

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server, Needs a command-line tool

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
AWS
Publisher
AWS (Official)
Source
aws/agent-toolkit-for-aws · plugins/aws-data-analytics/skills/creating-data-lake-table · commit 0a218f8
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • NOTICE (added by AutoGineer from NOTICE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Also distributed in
aws/agent-toolkit-for-aws

AutoGineer is not affiliated with or endorsed by AWS.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download creating-data-lake-table.zip