fix(graphql-model-transformer): derive imported DynamoDB table key schema from @primaryKey - #3523
Merged
Merged
Conversation
…hema from @PrimaryKey Imported Amplify-managed DynamoDB tables (Gen 1 -> Gen 2 migration via migratedAmplifyGen1DynamoDbTableMappings) hardcoded the table partition key to `id` when synthesizing the Custom::ImportedAmplifyDynamoDBTable resource. For owned tables the @PrimaryKey transformer corrects the key schema downstream via a CloudFormation property override, but that correction does not reach the TableManager import-validation path, which consumes the initial construct properties directly. As a result, any model declaring a custom @PrimaryKey (partition key other than `id`, and/or a sort key) failed import validation with "Imported table properties did not match the expected table properties", rolling back the whole branch stack (a failed CREATE that must then be deleted manually before retry). GSIs were unaffected because they are already derived from the model. Fix: in AmplifyDynamoModelResourceGenerator.createModelTable, for imported tables only, derive the partition key (and single/composite sort key) from the model's @PrimaryKey via getPrimaryKeyFieldNodes, mirroring how GSIs are derived. Owned tables are unchanged (still `id`, corrected downstream as before). Adds regression tests: imported table with a custom @PrimaryKey partition key, with a sort key, and the default-`id` no-regression case. Fixes #3489 Related: aws-amplify/amplify-backend#3281
soberm
reviewed
Aug 24, 2026
soberm
left a comment
There was a problem hiding this comment.
Reviewed the fix for deriving imported DynamoDB table key schema from @primaryKey. The core fix is correct and safely scoped to the imported-table path — no blocking issues. Leaving a few suggestions (test coverage for composite/numeric/enum keys) and nitpicks (DRY/typing).
…y coverage Address review feedback on imported-table key-schema derivation: - Resolve key attribute types with an enum-aware helper (mirrors the index transformer's attributeTypeFromType). Enum-backed @PrimaryKey / sort-key fields are valid and stored as strings; attributeTypeFromScalar throws on non-scalar (enum) types, which would have crashed synth. - Use ModelResourceIDs.ModelCompositeAttributeName for the composite sort-key attribute name instead of an inline join, and the CDK Attribute type. - Add regression tests for a composite sort key, numeric (Int/Float) keys, and an enum-typed primary key.
…a derivation Address further review feedback: - Extract the imported-table key-schema derivation into a private getImportedTableKeySchema method and a keyAttributeType helper, so createModelTable stays readable. - Add a regression test for the implicit-id fallback (an imported model with no id field and no @PrimaryKey still gets an id/HASH key schema).
Contributor
Author
|
Addressed the latest review batch in Applied
|
soberm
approved these changes
Aug 26, 2026
This was referenced Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When migrating a Gen 1 backend to Gen 2 with
migratedAmplifyGen1DynamoDbTableMappings, any model whose schema declares a custom@primaryKey(partition key other thanid) fails deployment. TheCustom::ImportedAmplifyDynamoDBTableresource is synthesized with an expected key schema ofid/HASH, so the TableManager import validation rejects the (correct) live Gen 1 table:The branch stack then rolls back (
ROLLBACK_COMPLETE); because it is a failed CREATE, the stack must be deleted manually before any retry.Reported in #3489 (surfaced downstream as aws-amplify/amplify-backend#3281).
Why it matters
This blocks Gen 1 → Gen 2 migration for any customer whose data model uses a custom primary key — a common pattern — mid-migration, with a rough manual-cleanup recovery. In a reported 19-model schema, 18 tables (default
idkeys, several with GSIs) migrated fine; the single model with a custom@primaryKeywas the only failure.Fix (symptom → root cause → change)
keySchema/attributeDefinitionsareid/HASHregardless of the model's@primaryKey.AmplifyDynamoModelResourceGenerator.createModelTableinstantiatesAmplifyDynamoDBTablewith a hardcodedpartitionKey: { name: 'id', type: STRING }for every table, including imported ones. For owned tables the@primaryKeytransformer (replaceDdbPrimaryKeyin the index transformer) corrects the key schema downstream viacfnTable.addPropertyOverride(...). That correction does not reach the imported-table validation path, which consumes the initial construct properties directly (import-table.ts→getExpectedKeySchemareturnscreateTableInput.KeySchemaverbatim). GSIs are unaffected because they are already derived from the model.createModelTable, for imported tables only, derive the partition key — and the sort key (single or composite) — from the model's@primaryKeyviagetPrimaryKeyFieldNodes, mirroring how GSIs are already derived from the model. Composite sort keys reuse the sameModelCompositeKeySeparator()join as the transformer'sgetSortKeyName. Owned tables are untouched (stillid, corrected downstream exactly as before).Tests
Added three regression tests in
amplify-dynamodb-table-generator.test.ts, each asserting the synthesizedCustom::ImportedAmplifyDynamoDBTableproperties:@primaryKey(partition key ≠id) →keySchema/attributeDefinitionsuseuserAuthenticating, notid.@primaryKeywith a sort key →keySchemais[HASH, RANGE]on the model fields (this case caught a gap in the first iteration and drove the sort-key handling).@primaryKey→ stillid/HASH(no regression).Verified these tests fail on the base code (imported table synthesizes
id/HASH) and pass with the fix — confirmed reproduction, not just static analysis.Manual verification
amplify-dynamodb-table-generator.test.ts: 7/7 pass.@aws-amplify/graphql-model-transformersuite: 12 suites / 203 tests / 87 snapshots pass — no snapshot drift (the change is gated onisTableImported).@aws-amplify/graphql-index-transformersuite: 93 tests pass.tsc --noEmitongraphql-model-transformer: clean.Screenshots
N/A — no user-visible UI change (GraphQL transformer synthesis only).