{"_id":"@aws-mdaa/s3-tables","_rev":"2-684882d3d8c548bd7522fe3e1cb67e1b","name":"@aws-mdaa/s3-tables","dist-tags":{"latest":"1.8.1"},"versions":{"1.8.0":{"name":"@aws-mdaa/s3-tables","version":"1.8.0","author":{"url":"https://aws.amazon.com/solutions","name":"Amazon Web Services"},"license":"Apache-2.0","_id":"@aws-mdaa/s3-tables@1.8.0","maintainers":[{"name":"mdaa-dev-team","email":"mdaa-dev-team@amazon.com"}],"homepage":"https://github.com/aws/modern-data-architecture-accelerator#readme","bugs":{"url":"https://github.com/aws/modern-data-architecture-accelerator/issues"},"bin":{"s3-tables-cdk":"bin/s3-tables.js"},"dist":{"shasum":"ce38a70590ced73dab7519fe8c1c4dcdd79439a5","tarball":"https://registry.npmjs.org/@aws-mdaa/s3-tables/-/s3-tables-1.8.0.tgz","fileCount":15,"integrity":"sha512-P7/qHfQjlpXA/MvJumdKGCwfENsrZnzpCXUjE6moZ/b5bRlJlRmoBWw2unBsjxBptDM1YXXLk+vGH+nN+Pd2NA==","signatures":[{"sig":"MEQCID6pdf8ZUNKJpvWrQh3w6joxfMPsogTVfxLzoTqQgznTAiBbWw57ihuN98xLpEeY3f6JbC241yVHQYPcBGeR8gG2lQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1287212},"main":"lib/index.js","mdaa":{"deployStage":"2"},"_from":"file:/Users/guoneng/.cache/mdaa-publish/mdaa/target/package-build/aws-mdaa-s3-tables-1.8.0.tgz","types":"lib/index.d.ts","scripts":{"cdk":"cdk","lint":"eslint --max-warnings 0 -c ../../../../eslint.config.mjs","test":"jest --passWithNoTests --coverage","build":"../../../../scripts/build/build_package.sh S3TablesConfigContents","watch":"tsc -w","test:package-docs":"../../../../scripts/generate_docs/test_package_docs.sh","test:update-baselines":"UPDATE_BASELINES=true jest --passWithNoTests --testPathPattern='.*\\.diff\\.test\\.ts'"},"_npmUser":{"name":"mdaa-dev-team","email":"mdaa-dev-team@amazon.com"},"_resolved":"/Users/guoneng/.cache/mdaa-publish/mdaa/target/package-build/aws-mdaa-s3-tables-1.8.0.tgz","_integrity":"sha512-P7/qHfQjlpXA/MvJumdKGCwfENsrZnzpCXUjE6moZ/b5bRlJlRmoBWw2unBsjxBptDM1YXXLk+vGH+nN+Pd2NA==","repository":{"url":"git+https://github.com/aws/modern-data-architecture-accelerator.git","type":"git"},"_npmVersion":"10.9.8","description":"MDAA S3 Tables module","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"8.18.0","yaml":"1.10.3","cdk-nag":"2.37.55","constructs":"10.6.0","aws-cdk-lib":"2.261.0","@aws-mdaa/app":"1.8.0","source-map-support":"0.5.21","@aws-mdaa/l3-construct":"1.8.0","@aws-mdaa/iam-role-helper":"1.8.0","@aws-mdaa/s3-tables-l3-construct":"1.8.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29.7.0","ts-jest":"29.4.9","ts-node":"10.9.2","typescript":"5.9.3","@types/jest":"29.5.14","@types/node":"22.9.0","@types/prettier":"2.6.0","@aws-mdaa/testing":"1.8.0","typescript-json-schema":"0.67.4"},"_npmOperationalInternal":{"tmp":"tmp/s3-tables_1.8.0_1788288116188_0.5878577847981192","host":"s3://npm-registry-packages-npm-production"}},"1.8.1":{"_id":"@aws-mdaa/s3-tables@1.8.1","bin":{"s3-tables-cdk":"bin/s3-tables.js"},"bugs":{"url":"https://github.com/aws/modern-data-architecture-accelerator/issues"},"dist":{"shasum":"7f3cc1126cc0e0a85c80ede63ed18bc662bd12f6","tarball":"https://registry.npmjs.org/@aws-mdaa/s3-tables/-/s3-tables-1.8.1.tgz","fileCount":15,"integrity":"sha512-smXSsjZ2JmO0Eq2Lu/NL8M1ikCCSGeG/7cZnsvqUMsBSWWicFvDSGEfAQsm8MqvFZGroX3/t/+V+4DKQkqh32Q==","signatures":[{"sig":"MEUCIQCYBC0J/+alQ0rd2Q1rQp/w4WgMTX9uqGu95zh4YNyXrQIgHlTvX4XgCx9BgBRc610C8alKbTROkYJ8ItjPJJoJyXM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDMrg4S/WBE6MdLF81pEdO1VIGjvmiW8YsF+lgc/viYCAiB93FnoHgWhsyl0CXiaSCI+SBOUeNY7qlzZ82H5TOQO9w=="}],"unpackedSize":1287212},"main":"lib/index.js","mdaa":{"deployStage":"2"},"name":"@aws-mdaa/s3-tables","_from":"file:/Users/guoneng/.cache/mdaa-publish/mdaa/target/package-build/aws-mdaa-s3-tables-1.8.1.tgz","types":"lib/index.d.ts","author":{"url":"https://aws.amazon.com/solutions","name":"Amazon Web Services"},"license":"Apache-2.0","scripts":{"cdk":"cdk","lint":"eslint --max-warnings 0 -c ../../../../eslint.config.mjs","test":"jest --passWithNoTests --coverage","build":"../../../../scripts/build/build_package.sh S3TablesConfigContents","watch":"tsc -w","test:package-docs":"../../../../scripts/generate_docs/test_package_docs.sh","test:update-baselines":"UPDATE_BASELINES=true jest --passWithNoTests --testPathPattern='.*\\.diff\\.test\\.ts'"},"version":"1.8.1","_npmUser":{"name":"mdaa-dev-team","email":"mdaa-dev-team@amazon.com"},"homepage":"https://github.com/aws/modern-data-architecture-accelerator#readme","_resolved":"/Users/guoneng/.cache/mdaa-publish/mdaa/target/package-build/aws-mdaa-s3-tables-1.8.1.tgz","_integrity":"sha512-smXSsjZ2JmO0Eq2Lu/NL8M1ikCCSGeG/7cZnsvqUMsBSWWicFvDSGEfAQsm8MqvFZGroX3/t/+V+4DKQkqh32Q==","repository":{"url":"git+https://github.com/aws/modern-data-architecture-accelerator.git","type":"git"},"_npmVersion":"10.9.8","description":"MDAA S3 Tables module","directories":{},"maintainers":[{"name":"mdaa-dev-team","email":"mdaa-dev-team@amazon.com"}],"_nodeVersion":"22.23.1","dependencies":{"ajv":"8.18.0","yaml":"1.10.3","cdk-nag":"2.37.55","constructs":"10.6.0","aws-cdk-lib":"2.261.0","@aws-mdaa/app":"1.8.1","source-map-support":"0.5.21","@aws-mdaa/l3-construct":"1.8.1","@aws-mdaa/iam-role-helper":"1.8.1","@aws-mdaa/s3-tables-l3-construct":"1.8.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29.7.0","ts-jest":"29.4.9","ts-node":"10.9.2","typescript":"5.9.3","@types/jest":"29.5.14","@types/node":"22.9.0","@types/prettier":"2.6.0","@aws-mdaa/testing":"1.8.1","typescript-json-schema":"0.68.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/s3-tables_1.8.1_1789417191208_0.3354946752245469"}}},"time":{"created":"2026-09-01T18:41:55.977Z","modified":"2026-09-14T20:19:51.468Z","1.8.0":"2026-09-01T18:41:56.337Z","1.8.1":"2026-09-14T20:19:51.310Z"},"bugs":{"url":"https://github.com/aws/modern-data-architecture-accelerator/issues"},"author":{"url":"https://aws.amazon.com/solutions","name":"Amazon Web Services"},"license":"Apache-2.0","homepage":"https://github.com/aws/modern-data-architecture-accelerator#readme","repository":{"url":"git+https://github.com/aws/modern-data-architecture-accelerator.git","type":"git"},"description":"MDAA S3 Tables module","maintainers":[{"name":"mdaa-dev-team","email":"mdaa-dev-team@amazon.com"}],"readme":"# S3 Tables\n\n> **Note:** This documentation is also available in a rendered format [here](https://aws.github.io/modern-data-architecture-accelerator/packages/apps/datalake/s3-tables-app/index.html).\n\nDeploys managed Apache Iceberg table buckets, namespaces, and tables via Amazon S3 Tables with mandatory KMS encryption, deny-by-default resource policies, TLS enforcement, and pre-defined permission sets (reader, writer, admin). Common scenarios include building a governed lakehouse with schema-defined Iceberg tables, providing fine-grained table-level access control for analytics teams, or establishing managed Iceberg storage with automatic compaction, snapshot management, and unreferenced file cleanup.\n\n---\n\n## Prerequisites\n\n- AWS account with access to Amazon S3 Tables (see [Region Availability](#aws-region-availability))\n- MDAA core infrastructure deployed (org, environment, domain context)\n- IAM roles defined for principals that require access to S3 Tables resources\n- **If bringing your own KMS key (`kmsKeyArn`):** the key policy must already grant the S3 Tables maintenance principal access, since MDAA cannot modify a key it does not own. Grant `kms:Decrypt` and `kms:GenerateDataKey` to service principal `maintenance.s3tables.amazonaws.com`, conditioned on `kms:EncryptionContext:aws:s3:arn` matching `<tableBucketArn>/*`. Without this grant, table creation fails with \"Insufficient access to perform table maintenance\". (MDAA-created keys receive this grant automatically.)\n- **To query tables from Athena, Redshift, EMR, or QuickSight:** the account/Region needs the S3 Tables analytics integration enabled once. Set `s3TablesIntegration.enabled: true` in the [LakeFormation Settings module](../../governance/lakeformation-settings-app/README.md) — it's account-level, so it's a one-time flag per account/Region no matter how many table buckets you deploy.\n\n---\n\n## Deployed Resources\n\nThis module deploys and integrates the following resources:\n\n| Resource | Description |\n|----------|-------------|\n| `AWS::S3Tables::TableBucket` | Managed Iceberg storage buckets with KMS encryption and optional maintenance configuration |\n| `AWS::S3Tables::Namespace` | Logical table groupings within table buckets |\n| `AWS::S3Tables::Table` | Apache Iceberg tables with schema, partition specifications, and sort orders |\n| `AWS::S3Tables::TableBucketPolicy` | Bucket-level resource policies (deny-by-default + TLS enforcement + grants) |\n| `AWS::S3Tables::TablePolicy` | Table-level resource policies (created for every table to carry the mandatory deny-non-TLS statement; table-level access grants are appended when declared) |\n| `AWS::KMS::Key` | Customer-managed encryption key (created when no external key ARN is provided) |\n| `AWS::SSM::Parameter` | Resource ARN/name exports for cross-stack discovery |\n\n---\n\n## Security and Compliance\n\nThis module is designed in alignment with MDAA security/compliance principles and CDK nag rulesets. Additional review is recommended prior to production deployment, ensuring organization-specific compliance requirements are met.\n\n- **Encryption at Rest**:\n  - KMS encryption is mandatory — there is no configuration option to deploy without encryption\n  - Customer-managed KMS key (either auto-created or externally provided)\n  - Key usage granted only to explicitly declared IAM role IDs via `aws:userId` conditions\n- **Encryption in Transit**:\n  - TLS enforced on all resource policies via `aws:SecureTransport` condition\n  - Every `TableBucketPolicy` and `TablePolicy` includes a deny-non-TLS statement\n- **Least Privilege**:\n  - Pre-defined permission sets (reader, writer, admin) map to fixed, minimal action sets\n  - Bucket-scope statements target the bucket ARN plus a contained-tables wildcard (`<bucketArn>/table/*`); table-scope statements target a single table ARN\n  - KMS key policy limits usage to declared principals only\n- **Deny-by-Default**:\n  - Table bucket policies always include a deny-all baseline — only explicitly granted principals (plus the CloudFormation execution role needed to deploy the stack) receive access; the baseline denies every other principal, including undeclared same-account principals\n  - If no IAM grants are declared, the policy contains the deny-non-TLS statement plus the deny-all baseline locked to the CloudFormation execution role only, so the bucket is not left open to same-account principals holding identity-based permissions\n- **Compliance Rulesets**:\n  - Passes cdk-nag checks for AwsSolutions, NIST 800-53 R5, HIPAA Security, and PCI DSS 3.2.1\n\n---\n\n## Configuration\n\n### MDAA Config\n\nAdd the following snippet to your `mdaa.yaml` under the `modules:` section of a domain/env in order to use this module:\n\n```yaml\ns3-tables: # Module name can be customized\n  module_path: '@aws-mdaa/s3-tables' # Must match module NPM package name\n  module_configs:\n    - ./s3-tables.yaml # Filename/path can be customized\n```\n\n### Module Config Samples and Variants\n\nCopy the contents of the relevant sample config below into the `./s3-tables.yaml` file referenced in the MDAA config snippet above.\n\n#### Minimal Configuration\n\nDeploys a single table bucket with one namespace, one Iceberg table, and one IAM grant using only required properties. Start here for a quick S3 Tables deployment before adding maintenance settings, partition strategies, or fine-grained table-level policies.\n\n[sample-config-minimal.yaml](sample_configs/sample-config-minimal.yaml)\n\n```yaml\n# Contents available via above link\n--8<-- \"target/docs/packages/apps/datalake/s3-tables-app/sample_configs/sample-config-minimal.yaml\"\n```\n\n#### Comprehensive Configuration\n\nExercises the full config surface: multiple table buckets, maintenance settings (compaction, snapshots, and unreferenced file removal), an externally provided KMS key (BYOK), all partition transforms, sort orders, and table-level access policies. Use it as a reference when adopting the more advanced features.\n\n[sample-config-comprehensive.yaml](sample_configs/sample-config-comprehensive.yaml)\n\n```yaml\n# Contents available via above link\n--8<-- \"target/docs/packages/apps/datalake/s3-tables-app/sample_configs/sample-config-comprehensive.yaml\"\n```\n\n---\n\n### Configuration Schema Reference\n\nThe module configuration follows the `roles → accessPolicies → tableBuckets` pattern established by the MDAA datalake module.\n\n#### Top-Level Fields\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `roles` | `Map<string, MdaaRoleRef[]>` | Yes | Logical role names mapped to IAM role references (ARN, name, ID, or SSM parameter) |\n| `accessPolicies` | `Map<string, AccessPolicyConfig>` | Yes (if referenced) | Named access policies mapping permission levels to logical role names |\n| `tableBuckets` | `Map<string, TableBucketConfig>` | Yes | Table bucket definitions with nested namespaces and tables |\n\n#### AccessPolicyConfig\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `ReadRoles` | `string[]` | No | Logical role names granted read-only access |\n| `ReadWriteRoles` | `string[]` | No | Logical role names granted read-write access |\n| `ReadWriteSuperRoles` | `string[]` | No | Logical role names granted full admin access |\n\n#### TableBucketConfig\n\n| Field | Type | Required | Constraints | Description |\n|-------|------|----------|-------------|-------------|\n| `accessPolicies` | `string[]` | Yes | Must reference top-level `accessPolicies` keys | Access policy names applied to this bucket |\n| `namespaces` | `Map<string, NamespaceConfig>` | Yes | At least one namespace | Namespace definitions within this bucket |\n| `maintenance` | `MaintenanceConfig` | No | See maintenance fields | Compaction, snapshot, and cleanup settings |\n| `kmsKeyArn` | `string` | No | Must match `arn:<partition>:kms:<region>:<account>:key/<key-id>` | External KMS key ARN; omit to auto-create. **BYOK:** the key policy must already grant `kms:Decrypt` + `kms:GenerateDataKey` to service principal `maintenance.s3tables.amazonaws.com` (conditioned on `kms:EncryptionContext:aws:s3:arn` matching `<tableBucketArn>/*`), or table creation fails — MDAA cannot modify a key it does not own |\n\n**Bucket name constraints:** Lowercase alphanumeric and hyphens only, 3-63 characters, must begin and end with a letter or number.\n\n#### NamespaceConfig\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `tables` | `Map<string, TableConfig>` | Yes | Table definitions within this namespace |\n\n**Namespace name constraints:** Lowercase letters, digits, and underscores only, 1-255 characters, must begin with a letter or number. Table names follow the same rules.\n\n#### TableConfig\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `columns` | `Map<string, IcebergColumnDef>` | Yes | Column definitions keyed by column name (at least one, max 200 per table); declaration order sets Iceberg field ids |\n| `partitions` | `Map<string, PartitionConfig>` | No | Partition specifications keyed by source column name |\n| `sortBy` | `Map<string, SortConfig>` | No | Sort order specifications keyed by source column name |\n| `accessPolicies` | `string[]` | No | Additive table-level access policy names |\n\n#### IcebergColumnDef\n\nColumns are declared as a keyed map where the **map key is the column name**; each value has the following fields.\n\n| Field | Type | Required | Valid Values |\n|-------|------|----------|--------------|\n| `type` | `string` | Yes | `boolean`, `int`, `long`, `float`, `double`, `decimal(p,s)`, `date`, `time`, `timestamp`, `timestamptz`, `string`, `uuid`, `fixed[n]`, `binary` (parameterized `decimal`/`fixed` must include their parameters) |\n| `required` | `boolean` | No | `true` or `false` (defaults to `false`) |\n\n#### PartitionConfig\n\nPartitions are declared as a keyed map where the **map key is the source column name** (must reference a column in `columns`); each value has the following fields.\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `transform` | `string` | Yes | One of: `identity`, `bucket`, `truncate`, `year`, `month`, `day`, `hour` |\n| `numBuckets` | `number` | Required for `bucket` | Positive integer specifying number of hash buckets |\n| `width` | `number` | Required for `truncate` | Positive integer specifying truncation width |\n\n#### SortConfig\n\nSort fields are declared as a keyed map where the **map key is the source column name** (must reference a column in `columns`); each value has the following fields.\n\n| Field | Type | Required | Valid Values |\n|-------|------|----------|--------------|\n| `direction` | `string` | Yes | `ASC` or `DESC` |\n| `nullOrder` | `string` | Yes | `nulls-first` or `nulls-last` |\n\n#### MaintenanceConfig\n\n| Field | Type | Range | Description |\n|-------|------|-------|-------------|\n| `compaction.targetFileSizeMB` | `number` | 64–512 | Target file size for compaction (applied per-table) |\n| `compaction.enabled` | `boolean` | — | Enable/disable compaction |\n| `snapshots.minToKeep` | `number` | 1–100 | Minimum snapshots to retain (applied per-table) |\n| `snapshots.maxAgeHours` | `number` | 1–8760 | Maximum snapshot age (applied per-table) |\n| `snapshots.enabled` | `boolean` | — | Enable/disable snapshot management |\n| `removeUnreferenced.afterDays` | `number` | 1–365 | Days before unreferenced files are removed (applied at the table-bucket level) |\n| `removeUnreferenced.keepNonCurrentDays` | `number` | 1–365 | Days to retain non-current files before removal |\n| `removeUnreferenced.enabled` | `boolean` | — | Enable/disable unreferenced file removal |\n\n> **Important — maintenance scope differs by setting.** The single bucket-level `maintenance` block does not all apply at the same scope:\n>\n> - **`removeUnreferenced` is a genuine bucket-wide setting.** It maps directly to the `AWS::S3Tables::TableBucket` unreferenced-file-removal property and therefore applies to **all tables in the bucket, including tables created outside MDAA**.\n> - **`compaction` and `snapshots` are per-table Iceberg (`AWS::S3Tables::Table`) settings.** They are not bucket properties; MDAA takes the single bucket-level block and **fans it out (copies it) onto every table MDAA provisions in that bucket**. Tables created outside MDAA are unaffected, and changing the block re-applies it to each MDAA-provisioned table.\n>\n> When maintenance fields are omitted entirely, S3 Tables applies its service default maintenance behavior.\n\n---\n\n[Config Schema Docs](SCHEMA.md)\n\n---\n\n## Deployment\n\nDeploy the module using the standard MDAA deployment process:\n\n1. Define IAM roles in your MDAA roles module (or reference existing roles by ARN).\n2. Create a module config YAML file referencing those roles (see [Configuration](#configuration)).\n3. Add the module to your `mdaa.yaml` under the appropriate domain/environment.\n4. Run the MDAA deployment:\n\n```bash\nnpx mdaa deploy\n```\n\nThe module will:\n\n- Validate configuration against the JSON Schema before synthesis\n- Create KMS key (if no external ARN provided)\n- Provision table buckets with encryption and maintenance settings\n- Create namespaces and Iceberg tables with schema definitions\n- Apply resource policies with deny-by-default + TLS enforcement + grants\n- Export resource ARNs and names to SSM Parameter Store\n\n---\n\n## Permission Sets Reference\n\nPermission sets abstract raw S3 Tables API actions into simple named levels. Each level includes all actions from lower levels.\n\n### Bucket-Scope Permission Sets\n\n| Level | Actions |\n|-------|---------|\n| **reader** | `GetTable`, `GetTableData`, `GetTableMetadataLocation`, `GetNamespace`, `GetTableBucket`, `ListTables`, `ListNamespaces` |\n| **writer** | All reader + `PutTableData`, `UpdateTableMetadataLocation` |\n| **admin** | All writer + `CreateTable`, `DeleteTable`, `RenameTable`, `CreateNamespace`, `DeleteNamespace` (policy-write actions are deliberately excluded so admins cannot replace the resource policy) |\n\n### Table-Scope Permission Sets\n\n| Level | Actions |\n|-------|---------|\n| **reader** | `GetTable`, `GetTableData`, `GetTableMetadataLocation` |\n| **writer** | All reader + `PutTableData`, `UpdateTableMetadataLocation` |\n| **admin** | All writer + `DeleteTable`, `RenameTable` (policy-write actions are deliberately excluded so admins cannot replace the resource policy) |\n\nAll actions use the `s3tables:` service prefix (e.g., `s3tables:GetTable`).\n\n---\n\n## AWS Region Availability\n\nAmazon S3 Tables availability varies by AWS region and changes over time. Check the [AWS Regional Services List](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/) for the current list of regions where Amazon S3 Tables is available before deploying.\n\n---\n\n## Service Quotas\n\n| Quota | Default Limit | Adjustable |\n|-------|---------------|------------|\n| Table buckets per account per region | 10 | Yes |\n| Namespaces per table bucket | 10,000 | No |\n| Tables per namespace | 10,000 | No |\n\nRequest quota increases through the [AWS Service Quotas console](https://console.aws.amazon.com/servicequotas/) if needed.\n\n---\n\n## Iceberg Schema Evolution\n\nS3 Tables manages Apache Iceberg tables with built-in schema and partition evolution support. Understanding which changes are non-destructive (in-place update) vs. destructive (requires table recreation) is critical for operational planning.\n\n### Non-Destructive Changes (Update Config and Redeploy)\n\nThese changes can be applied by updating the module configuration and redeploying:\n\n| Change | Details |\n|--------|---------|\n| Adding columns | Add new entries to the `columns` map |\n| Reordering columns | Change the order of columns in the configuration |\n| Adding partition fields | Add new entries to the `partitions` map |\n\nS3 Tables handles Iceberg schema evolution transparently for additive changes. Existing data remains readable with the new schema.\n\n### Destructive Changes (Require Table Recreation)\n\nThese changes cannot be applied in-place and require dropping and recreating the table:\n\n| Change | Details |\n|--------|---------|\n| Removing columns | Removing a column from the `columns` map |\n| Changing column types | Modifying a column's data type |\n| Removing partition fields | Removing entries from the `partitions` map |\n\n**Procedure for destructive changes:**\n\n1. Remove the table from the module configuration\n2. Deploy to delete the table resource\n3. Add the table back with the updated schema\n4. Deploy again to create the table with the new definition\n\n> **Warning:** Destructive schema changes result in data loss for the affected table. Ensure data is backed up or migrated before proceeding.\n\n### Partition Evolution\n\n| Change | Type | Notes |\n|--------|------|-------|\n| Adding partition fields | Non-destructive | New partition fields apply to newly written data; existing data retains its original partitioning |\n| Removing partition fields | Destructive | Requires table recreation |\n| Changing partition transforms | Destructive | Requires table recreation |\n\n---\n\n## Related Modules\n\n- [Data Lake](../datalake-app/README.md) — Deploy S3-based data lake buckets for use alongside S3 Tables\n- [Athena Workgroup](../athena-workgroup-app/README.md) — Deploy Athena workgroups for querying Iceberg tables\n","readmeFilename":"README.md"}