How to run it
Every way Dynalite is distributed, each linking to the project's own documentation for it. These are the project's claims, not the suite's measurements.
Needs: Node 20+
Per-region divergence
The headline is 2 regions, measured against 2 of 33 observed regions, and scored in eu-south-2. Real DynamoDB doesn't behave identically in every region, so a target can match some regions more closely than others. Each figure below is divergence in those regions, best first. eu-west-2 is marked as the historical baseline, and a region that couldn't be resolved this sweep is flagged rather than counted as a disagreement.
Feature support
Measured across the suite's tests for each feature. Compare with other emulators.
Core DynamoDB
- Vector search
- Dynalite Vector search: not supported (52 skip)
- GSI
- Dynalite GSI: partially supported (55 pass, 34 fail, 87 skip)
- LSI
- Dynalite LSI: partially supported (47 pass, 24 fail, 87 skip)
- PartiQL
- Dynalite PartiQL: not supported (210 skip)
- Transactions
- Dynalite Transactions: partially supported (4 pass, 17 fail, 106 skip)
- Streams
- Dynalite Streams: not supported (18 skip)
- TTL
- Dynalite TTL: partially supported (2 pass, 5 fail)
- Legacy params
- Dynalite Legacy params: partially supported (47 pass, 2 fail)
Other AWS services
- Backups / PITR
- Dynalite Backups / PITR: not supported (5 skip)
- Export / import
- Dynalite Export / import: not supported (2 skip)
- Kinesis
- Dynalite Kinesis: not supported (1 skip)
- Resource policies
- Dynalite Resource policies: not supported (2 skip)
- Contributor Insights
- Dynalite Contributor Insights: not supported (2 skip)
- Account API
- Dynalite Account API: not supported (2 skip)
Fully supports
Operation areas this target implements completely - every test passes, nothing skipped. Areas it only partly gets wrong are in “Where it falls short” below; the ones it only partly attempts are in “What it doesn’t attempt”.
- batchGetItem tier 1
- deleteItem tier 1
- deleteTable tier 1
- describeTable tier 1
- getItem tier 1
- listTables tier 1
Divergence and coverage over time
Both are plotted because neither reads correctly alone. Divergence falls when a target stops attempting an operation it used to get wrong, so a fall in the first plot is only an improvement if the second one holds.
Divergence
Coverage
By operation
Every operation this target implements, with how much of it diverges and how much of it it covers, on the same two axes as the figures above. The counts are fails over the operation's whole size. full, partial, failing, unsupported. The emulator directory lists support across targets.
Tier 1 - Core
- batchGetItem 0/15 0.0% 100.0% batchGetItem: supported, diverges on 0.0% of it, covers 100.0% (15 pass)
- batchWriteItem 1/18 5.6% 100.0% batchWriteItem: partially supported, diverges on 5.6% of it, covers 100.0% (17 pass, 1 fail)
- createTable 7/30 23.3% 100.0% createTable: partially supported, diverges on 23.3% of it, covers 100.0% (23 pass, 7 fail)
- deleteItem 0/13 0.0% 100.0% deleteItem: supported, diverges on 0.0% of it, covers 100.0% (13 pass)
- deleteTable 0/3 0.0% 100.0% deleteTable: supported, diverges on 0.0% of it, covers 100.0% (3 pass)
- describeTable 0/4 0.0% 100.0% describeTable: supported, diverges on 0.0% of it, covers 100.0% (4 pass)
- getItem 0/39 0.0% 100.0% getItem: supported, diverges on 0.0% of it, covers 100.0% (39 pass)
- listTables 0/5 0.0% 100.0% listTables: supported, diverges on 0.0% of it, covers 100.0% (5 pass)
- putItem 27/129 20.9% 100.0% putItem: partially supported, diverges on 20.9% of it, covers 100.0% (102 pass, 27 fail)
- query 5/95 5.3% 100.0% query: partially supported, diverges on 5.3% of it, covers 100.0% (90 pass, 5 fail)
- scan 6/60 10.0% 100.0% scan: partially supported, diverges on 10.0% of it, covers 100.0% (54 pass, 6 fail)
- updateItem 2/70 2.9% 100.0% updateItem: partially supported, diverges on 2.9% of it, covers 100.0% (68 pass, 2 fail)
- updateTable 5/15 33.3% 100.0% updateTable: partially supported, diverges on 33.3% of it, covers 100.0% (10 pass, 5 fail)
Tier 2 - Complete
- account 0/2 · 2 skip n/a 0.0% account: unsupported, implements none of it (2 skip)
- backups 0/5 · 5 skip n/a 0.0% backups: unsupported, implements none of it (5 skip)
- contributorInsights 0/2 · 2 skip n/a 0.0% contributorInsights: unsupported, implements none of it (2 skip)
- export 0/2 · 2 skip n/a 0.0% export: unsupported, implements none of it (2 skip)
- kinesis 0/1 · 1 skip n/a 0.0% kinesis: unsupported, implements none of it (1 skip)
- partiql 0/186 · 186 skip n/a 0.0% partiql: unsupported, implements none of it (186 skip)
- resourcePolicy 0/2 · 2 skip n/a 0.0% resourcePolicy: unsupported, implements none of it (2 skip)
- streams 0/18 · 18 skip n/a 0.0% streams: unsupported, implements none of it (18 skip)
- tags 2/8 25.0% 100.0% tags: partially supported, diverges on 25.0% of it, covers 100.0% (6 pass, 2 fail)
- transactions 11/62 · 51 skip 17.7% 17.7% transactions: failing, diverges on 17.7% of it, covers 17.7% (11 fail, 51 skip)
- ttl 5/7 71.4% 100.0% ttl: partially supported, diverges on 71.4% of it, covers 100.0% (2 pass, 5 fail)
- updateTable 10/14 71.4% 100.0% updateTable: partially supported, diverges on 71.4% of it, covers 100.0% (4 pass, 10 fail)
- vectorSearch 0/36 · 36 skip n/a 0.0% vectorSearch: unsupported, implements none of it (36 skip)
Tier 3 - Strict
- error-messages 39/185 · 61 skip 21.1% 67.0% error-messages: partially supported, diverges on 21.1% of it, covers 67.0% (85 pass, 39 fail, 61 skip)
- legacy-api 1/42 2.4% 100.0% legacy-api: partially supported, diverges on 2.4% of it, covers 100.0% (41 pass, 1 fail)
- limits 20/164 · 29 skip 12.2% 82.3% limits: partially supported, diverges on 12.2% of it, covers 82.3% (115 pass, 20 fail, 29 skip)
- validation-ordering 10/34 · 3 skip 29.4% 91.2% validation-ordering: partially supported, diverges on 29.4% of it, covers 91.2% (21 pass, 10 fail, 3 skip)
Where it falls short
Operations Dynalite implements and answers differently from real DynamoDB, biggest gap first. This is what its divergence figure counts. Open one for the exact tests, or see the conformance suite.
-
error-messages Tier 3 39 diverging 61 not attempted
View these tests in the suite →- BatchGetItem - exact error messages empty RequestItems: full required-parameter error source:27
- BatchGetItem - exact error messages > 100 keys across all tables: interpolated full error source:47
- BatchGetItem - exact error messages empty-binary lookup key: full empty-value message source:141
- BatchGetItem - exact error messages mixing ProjectionExpression on one table and AttributesToGet on another is rejected source:165
- BatchWriteItem - exact error messages empty RequestItems: full required-parameter error source:44
- BatchWriteItem - exact error messages > 25 requests: anchored regex on the constraint phrase source:91
- BatchWriteItem - exact error messages empty-binary delete-request key: full empty-value message source:157
- Conditional check - exact error messages ReturnValuesOnConditionCheckFailure: ALL_OLD returns item in error source:210
- CreateTable - exact error messages short table name (2 chars): minimum length 3 error source:52
- CreateTable - exact error messages more than 2 KeySchema elements source:112
- CreateTable - exact error messages GSI INCLUDE projection without NonKeyAttributes: full missing-attributes message source:282
- CreateTable - exact error messages LSI INCLUDE projection without NonKeyAttributes: full missing-attributes message source:321
- CreateTable - exact error messages StreamSpecification StreamEnabled:false with a StreamViewType: full conflict message source:345
- DeleteItem - exact error messages empty-binary key value: full ValidationException message source:90
- GetItem - exact error messages invalid ProjectionExpression syntax: full parser error source:69
- GetItem - exact error messages empty-binary key value: full ValidationException message source:89
- BatchWriteItem - index key error messages empty-string index key: full secondary-index-key message source:52
- BatchWriteItem - index key error messages empty-binary index key: full secondary-index-key message source:52
- PutItem - index key error messages empty-binary index key value: full secondary-index-key message source:124
- UpdateItem - index key error messages empty-binary index key value: full secondary-index-key message source:148
- Scan - index error messages ConsistentRead on a GSI: full consistent-reads-unsupported message source:52
- PutItem - exact error messages empty table name: minimum length 1 error source:62
- PutItem - exact error messages duplicate empty string members in SS: full duplicates error source:214
- PutItem - exact error messages duplicate zero-length members in BS: full duplicates error source:238
- Query - exact error messages Limit of 0 source:110
- Query - exact error messages Select SPECIFIC_ATTRIBUTES without ProjectionExpression: full required-projection message source:212
- Scan - exact error messages Segment without TotalSegments: full required-parameter error source:29
- Scan - exact error messages Segment >= TotalSegments: full out-of-range error source:62
- Scan - exact error messages Limit of 0: full minimum-value error source:103
- Scan - exact error messages negative Segment: full minimum-value error source:127
- Scan - exact error messages malformed ExclusiveStartKey: long schema-mismatch error source:211
- Scan - exact error messages Select SPECIFIC_ATTRIBUTES without ProjectionExpression: full required-projection message source:234
- TransactGetItems - exact error messages empty TransactItems: full minimum-length error source:27
- TransactGetItems - exact error messages > 100 gets: anchored regex on the constraint phrase source:63
- TransactGetItems - exact error messages non-existent table: full ResourceNotFoundException message source:84
- TransactGetItems - exact error messages invalid ProjectionExpression syntax: full parser error source:114
- TransactGetItems - exact error messages missing key attribute: action-level ValidationError surfaces as TransactionCanceledException source:140
- UpdateItem - exact error messages invalid UpdateExpression syntax source:68
- UpdateItem - exact error messages empty-binary key value: full ValidationException message source:212
- Conditional check - exact error messages TransactionCanceledException message format
- PartiQL - exact error messages DELETE RETURNING MODIFIED OLD * - exact message
- PartiQL - exact error messages DELETE RETURNING ALL NEW * - exact message
- PartiQL - exact error messages DELETE RETURNING MODIFIED NEW * - exact message
- PartiQL - exact error messages ExecuteTransaction with a RETURNING member - exact message
- PartiQL - exact error messages an ordering comparison on an unordered operand - exact message
- PartiQL index qualifier - exact error messages unprojected filter attribute on a GSI - exact message
- PartiQL index qualifier - exact error messages unprojected filter attribute on an LSI - same wording, no Local prefix
- PartiQL index qualifier - exact error messages unprojected projection attribute on a GSI - exact message
- PartiQL index qualifier - exact error messages a qualifier naming no index - exact message, with no name appended
- PartiQL index qualifier - exact error messages a qualifier naming the table itself - same message
- PartiQL index qualifier - exact error messages a three-component path - exact message
- PartiQL index qualifier - exact error messages an empty index component - exact message
- PartiQL index qualifier - exact error messages ConsistentRead against a GSI qualifier - exact message
- PartiQL index qualifier - exact error messages an index-qualified read inside a transaction - exact message
- SearchVectors - exact error messages TopK above the maximum
- SearchVectors - exact error messages missing SearchConditionExpression against a HASH-schema index
- SearchVectors - exact error messages non-equality comparator on the HASH element
- SearchVectors - exact error messages non-equality comparator on an INLINE_FILTER element
- SearchVectors - exact error messages query vector dimension mismatch
- SearchVectors - exact error messages condition attribute outside the SearchSchema
- SearchVectors - exact error messages L-wrapped search vector
- TransactWriteItems - index key error messages Put wrong-typed index key: cancelled with full ValidationError reason
- TransactWriteItems - index key error messages Put non-scalar index key: cancelled with full ValidationError reason
- TransactWriteItems - index key error messages Update wrong-typed index key: cancelled with full ValidationError reason
- TransactWriteItems - index key error messages Update non-scalar index key: cancelled with full ValidationError reason
- TransactWriteItems - index key error messages Put empty-string index key: top-level ValidationException
- TransactWriteItems - index key error messages Update empty-string index key: top-level ValidationException
- TransactWriteItems - index key error messages Put empty-binary index key: top-level ValidationException
- TransactWriteItems - index key error messages Update empty-binary index key: top-level ValidationException
- TransactWriteItems - exact error messages empty TransactItems: full minimum-length error
- TransactWriteItems - exact error messages > 100 actions: anchored regex on the constraint phrase
- TransactWriteItems - exact error messages duplicate target keys in same transaction: full multi-op error
- TransactWriteItems - exact error messages non-existent table: full ResourceNotFoundException message
- TransactWriteItems - exact error messages two failing actions: multi-reason TransactionCanceledException
- TransactWriteItems - exact error messages one passing, one failing: positional reason codes (None for the survivor)
- TransactWriteItems - exact error messages Put wrong-typed table key: cancelled with full ValidationError reason
- TransactWriteItems - exact error messages Put non-scalar table key: cancelled with full ValidationError reason
- TransactWriteItems - exact error messages Put empty-string table key: top-level ValidationException
- TransactWriteItems - exact error messages Update empty-string Key: top-level empty-value message
- TransactWriteItems - exact error messages Delete empty-string Key: top-level empty-value message
- TransactWriteItems - exact error messages ConditionCheck empty-string Key: top-level empty-value message
- TransactWriteItems - exact error messages Update wrong-typed Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages Update non-scalar Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages Delete wrong-typed Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages Delete non-scalar Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages ConditionCheck wrong-typed Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages ConditionCheck non-scalar Key: cancelled with schema-mismatch reason
- TransactWriteItems - exact error messages Put empty-binary item key: top-level empty-value message
- TransactWriteItems - exact error messages Update empty-binary Key: top-level empty-value message
- TransactWriteItems - exact error messages Delete empty-binary Key: top-level empty-value message
- TransactWriteItems - exact error messages ConditionCheck empty-binary Key: top-level empty-value message
- CreateTable vector indexes - exact error messages vector index on a provisioned table
- CreateTable vector indexes - exact error messages SearchSchema attribute missing from AttributeDefinitions
- CreateTable vector indexes - exact error messages Dimensions above the 4096 maximum
- CreateTable vector indexes - exact error messages more vector indexes than the per-table limit
- CreateTable vector indexes - exact error messages two indexes on one attribute with different Dimensions
- PutItem vector writes - exact error messages vector with the wrong dimension count
- PutItem vector writes - exact error messages vector element that is not a number, naming the element
- PutItem vector writes - exact error messages vector attribute that is not a list
- PutItem vector writes - exact error messages empty string in the SearchSchema HASH attribute
-
transactions Tier 2 11 diverging 51 not attempted
View these tests in the suite →- TransactGetItems - basic gets multiple items atomically source:46
- TransactGetItems - basic gets items across tables (hashTableDef + compositeTableDef) source:83
- TransactGetItems - basic returns empty Item for non-existing items in the mix source:115
- TransactGetItems - basic gets a single item source:152
- TransactGetItems - basic returns all items when all exist source:180
- TransactGetItems - validation rejects empty TransactItems source:201
- TransactGetItems - validation rejects get on non-existent table source:213
- TransactGetItems - validation rejects duplicate keys in same transaction source:232
- TransactGetItems - ConsumedCapacity charges 2 read capacity units per item, including a missing item source:274
- TransactGetItems - ConsumedCapacity INDEXES breakdown includes the table read capacity units source:297
- TransactGetItems - projection matching nothing omits Item when the projection matches no attribute on a present item source:326
- TransactWriteItems - basic functionality executes Put + Update + Delete atomically
- TransactWriteItems - basic functionality commits a Put whose string set carries an empty member
- TransactWriteItems - basic functionality succeeds when ConditionCheck condition is met
- TransactWriteItems - basic functionality rolls back entire transaction when ConditionCheck fails
- TransactWriteItems - basic functionality applies ConditionExpression on Put action
- TransactWriteItems - basic functionality applies ConditionExpression on Update action
- TransactWriteItems - basic functionality applies ConditionExpression on Delete action
- TransactWriteItems - basic functionality executes cross-table transaction (hashTableDef + compositeTableDef)
- TransactWriteItems - basic functionality supports idempotency via ClientRequestToken
- TransactWriteItems - basic functionality rejects same ClientRequestToken with different payload
- TransactWriteItems - basic functionality includes CancellationReasons in error when condition fails
- TransactWriteItems - basic functionality returns ALL_OLD item via ReturnValuesOnConditionCheckFailure
- TransactWriteItems - multiple items puts multiple items in one transaction
- TransactWriteItems - multiple items updates multiple items in one transaction
- TransactWriteItems - multiple items deletes multiple items in one transaction
- TransactWriteItems - validation rejects duplicate target items in same transaction
- TransactWriteItems - validation rejects empty TransactItems
- TransactWriteItems - validation rejects transaction on non-existent table
- TransactWriteItems - validation Put with a wrong-typed table key cancels with a ValidationError reason
- TransactWriteItems - validation Put with a non-scalar table key cancels with a ValidationError reason
- TransactWriteItems - validation Put with an empty-string table key is a top-level ValidationException
- TransactWriteItems - validation Update with an empty-string Key is a top-level ValidationException
- TransactWriteItems - validation Delete with an empty-string Key is a top-level ValidationException
- TransactWriteItems - validation ConditionCheck with an empty-string Key is a top-level ValidationException
- TransactWriteItems - validation Update with a wrong-typed Key cancels with a ValidationError reason
- TransactWriteItems - validation Update with a non-scalar Key cancels with a ValidationError reason
- TransactWriteItems - validation Delete with a wrong-typed Key cancels with a ValidationError reason
- TransactWriteItems - validation Delete with a non-scalar Key cancels with a ValidationError reason
- TransactWriteItems - validation ConditionCheck with a wrong-typed Key cancels with a ValidationError reason
- TransactWriteItems - validation ConditionCheck with a non-scalar Key cancels with a ValidationError reason
- TransactWriteItems - validation Update with attribute_exists rejects non-existent item
- TransactWriteItems - validation Update with attribute_not_exists upserts on non-existent key
- TransactWriteItems - validation Update with comparison condition cancels on non-existent key; no ghost item
- TransactWriteItems - validation Update with combined attribute_exists + equality cancels on non-existent key; no ghost item
- TransactWriteItems - validation mixed transaction: one passing, one failing on non-existent cancels everything
- TransactWriteItems - ConditionExpression parens Put with per-condition parens succeeds on fresh key
- TransactWriteItems - ConditionExpression parens Update with full-expression wrap succeeds when condition holds
- TransactWriteItems - ConditionExpression parens Delete with non-redundant nested parens succeeds when condition holds
- TransactWriteItems - ConditionExpression parens ConditionCheck with per-condition parens passes when condition holds
- TransactWriteItems - ConditionExpression parens cancels transaction when any parenthesised condition fails
- TransactWriteItems - ConsumedCapacity charges 2 write capacity units per item
- TransactWriteItems - ConsumedCapacity: conditional, check, replay, cancel a passing conditional write costs the same 2 WCU/item as an unconditional one
- TransactWriteItems - ConsumedCapacity: conditional, check, replay, cancel a standalone ConditionCheck action costs 2 write capacity units
- TransactWriteItems - ConsumedCapacity: conditional, check, replay, cancel reports write capacity on the first call and read capacity on a same-token replay
- TransactWriteItems - ConsumedCapacity: conditional, check, replay, cancel a cancelled conditional transaction reports no consumed capacity
- TransactWriteItems - index key validation Put with a wrong-typed index key cancels with a ValidationError reason
- TransactWriteItems - index key validation Put with a non-scalar index key cancels with a ValidationError reason
- TransactWriteItems - index key validation Update setting a wrong-typed index key cancels with a ValidationError reason
- TransactWriteItems - index key validation Update setting a non-scalar index key cancels with a ValidationError reason
- TransactWriteItems - index key validation Put with an empty-string index key is a top-level ValidationException
- TransactWriteItems - index key validation Update setting an empty-string index key is a top-level ValidationException
-
limits Tier 3 20 diverging 29 not attempted
View these tests in the suite →- Empty values - strings, binary, and sets duplicate empty string members in SS are rejected as duplicates source:238
- Empty values - strings, binary, and sets duplicate zero-length members in BS are rejected as duplicates source:252
- Expression size limit (4KB) - UpdateExpression rejects an UpdateExpression over the 4096-byte limit source:132
- Expression size limit (4KB) - ConditionExpression rejects a ConditionExpression over the 4096-byte limit source:163
- Expression size limit (4KB) - Query FilterExpression rejects a Query FilterExpression over the 4096-byte limit source:206
- Expression size limit (4KB) - Scan FilterExpression rejects a Scan FilterExpression over the 4096-byte limit source:241
- Expression size limit (4KB) - ProjectionExpression rejects a ProjectionExpression over the 4096-byte limit source:280
- Item size limit by surface - UpdateItem does not charge for the key sits below 409,600 at a one-byte key, so the exclusion binds source:416
- Item size limit by surface - UpdateItem does not charge for the key buys back the same headroom from the key name as from the key value source:416
- Item size limit by surface - UpdateItem does not charge for the key buys back a sort key’s own bytes as well source:416
- Item size limit by surface - UpdateItem charges per action charges a second SET clause exactly 19 bytes source:416
- Item size limit by surface - UpdateItem charges per action charges a REMOVE alongside a SET exactly 2 bytes source:416
- Item size limit by surface - UpdateItem charges per action charges the clause, not the value it writes source:416
- Item size limit by surface - UpdateItem charges per action does not charge for an attribute the statement leaves alone source:416
- Item size limit by surface - UpdateItem charges per action charges the clause, not the attribute name or its alias source:416
- Item size limit by surface - UpdateItem through a document path charges a SET through a list index exactly one byte more source:690
- Nesting depth - 32-level document limit rejects a stored attribute nested 32 levels (leaf at level 33) source:65
- Nesting depth - 32-level document limit rejects a 32-level ExpressionAttributeValue with ValidationException source:113
- Nesting depth - BatchWriteItem rejects a Put item nested 32 levels (leaf at level 33) source:167
- Number precision - DynamoDB number limits and edge cases rejects arithmetic that overflows the supported number magnitude source:407
- Expression size limit (4KB) - TransactWriteItems accepts a Put ConditionExpression at the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems rejects a Put ConditionExpression over the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems accepts an Update UpdateExpression at the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems rejects an Update UpdateExpression over the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems rejects a Delete ConditionExpression over the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems rejects a ConditionCheck ConditionExpression over the 4096-byte limit
- Expression size limit (4KB) - TransactWriteItems rejects the whole request when only the second member is oversized
- Item size limit by surface - PartiQL INSERT accepts an item of exactly 409,600 bytes
- Item size limit by surface - PartiQL INSERT refuses it one byte over, with the put wording
- Item size limit by surface - PartiQL UPDATE accepts a finished item of exactly 409,600 bytes
- Item size limit by surface - PartiQL UPDATE refuses it one byte over, with the update wording
- Item size limit by surface - TransactWriteItems a Put accepts an item of exactly 409,600 bytes
- Item size limit by surface - TransactWriteItems a Put one byte over raises ValidationException, not a cancellation
- Item size limit by surface - TransactWriteItems an Update accepts a finished item of exactly 409,600 bytes
- Item size limit by surface - TransactWriteItems an Update one byte over surfaces as a cancellation, with the update wording
- Item size limit by surface - TransactWriteItems answers the same way for a fresh key and for an existing row
- Item size limit by surface - a PartiQL UPDATE does not inherit the exclusion writes what UpdateItem refuses at the same key
- Item size limit by surface - a transacted Update does not inherit the exclusion writes what UpdateItem refuses at the same key
- Nesting depth - TransactWriteItems accepts a Put item nested 31 levels (leaf at level 32)
- Nesting depth - TransactWriteItems rejects a Put item nested 32 levels with a top-level ValidationException
- Nesting depth - TransactWriteItems cancels an Update that writes a 32-level value into the item with a ValidationError reason
- Nesting depth - TransactWriteItems does not check the depth of an Update ExpressionAttributeValue (the condition is evaluated)
- Nesting depth - TransactWriteItems does not check the depth of a ConditionCheck ExpressionAttributeValue (the condition is evaluated)
- TransactWriteItems limits TransactWriteItems with exactly 100 Put actions succeeds
- TransactWriteItems limits TransactWriteItems with 101 actions fails with ValidationException
- TransactWriteItems limits TransactWriteItems total item size approaching 4MB succeeds
- TransactWriteItems limits TransactWriteItems total item size over 4MB fails with ValidationException
- TransactGetItems limits TransactGetItems with exactly 100 items succeeds
- TransactGetItems limits TransactGetItems with 101 items fails with ValidationException
-
putItem Tier 1 27 diverging
View these tests in the suite →- PutItem - ConditionExpression returns the conflicting item via ReturnValuesOnConditionCheckFailure on a failed Put source:227
- PutItem - index write capacity reports the GSI write beside the table write and sums them source:43
- PutItem - index write capacity folds the index cost into TOTAL with no breakdown arms source:121
- PutItem - index write capacity reports the LSI write and folds it into the total source:43
- PutItem - index write capacity reports both arms when a write touches both index kinds source:43
- PutItem - index write capacity charges an identical overwrite no index writes at all source:43
- UpdateItem - index write-capacity ladder charges nothing on the index for a non-projected attribute source:43
- UpdateItem - index write-capacity ladder charges one index write for a projected non-key attribute source:43
- UpdateItem - index write-capacity ladder charges two index writes for a key change: delete plus insert source:43
- UpdateItem - index write-capacity ladder charges one index write to remove the key: delete only source:43
- UpdateItem - index write-capacity ladder walks the same ladder on the LSI key source:43
- DeleteItem - index write capacity charges one write per index the item occupied source:43
- BatchWriteItem - index write capacity reports the per-table entry with the arms the batch actually touched source:43
- PutItem - index key validation rejects an empty-string index key attribute source:46
- ReturnItemCollectionMetrics PutItem with SIZE returns ItemCollectionMetrics source:37
- ReturnItemCollectionMetrics DeleteItem with SIZE returns ItemCollectionMetrics source:65
- ReturnItemCollectionMetrics UpdateItem with SIZE returns ItemCollectionMetrics source:95
- PutItem - number format accepts "+5" and stores it as "5" source:76
- PutItem - number format accepts "+1.5" and stores it as "1.5" source:76
- PutItem - number format accepts "+0" and stores it as "0" source:76
- PutItem - number format accepts "+0.0" and stores it as "0" source:76
- PutItem - number format accepts "+1e2" and stores it as "100" source:76
- PutItem - number format accepts "+.5" and stores it as "0.5" source:76
- PutItem - number format accepts "+1e-2" and stores it as "0.01" source:76
- PutItem - number format accepts a leading + on a numeric sort key and normalises it source:112
- PutItem - validation rejects duplicate empty string members in a string set source:88
- PutItem - validation rejects duplicate zero-length members in a binary set source:101
-
validation-ordering Tier 3 10 diverging 3 not attempted
View these tests in the suite →- CreateTable - validation ordering empty TableName reports only tableName constraint source:23
- CreateTable - validation ordering invalid table name pattern reports only tableName source:41
- DeleteItem - validation ordering empty TableName reports only tableName constraint source:26
- Non-existent index - error surface UpdateTable deleting a non-existent GSI reports ResourceNotFoundException source:66
- PutItem - validation ordering empty TableName reports tableName constraint (stops early) source:28
- PutItem - validation ordering empty TableName with invalid ReturnValues reports only tableName source:55
- Query - validation ordering reports invalid Limit value source:49
- Scan - validation ordering rejects Segment without TotalSegments source:21
- UpdateItem - validation ordering empty TableName reports only tableName constraint source:27
- UpdateItem - validation ordering rejects invalid ReturnValues (UpdateItem reports the first enum error) source:54
- PartiQL - validation ordering the operand-type check fires ahead of table resolution
- PartiQL - validation ordering a well-formed statement on the same table reports it missing
- PartiQL - validation ordering an empty path component fires ahead of table resolution
-
updateTable Tier 2 10 diverging
View these tests in the suite →- UpdateTable - add GSI adds a hash-only GSI to an existing table source:137
- UpdateTable - add GSI adds a composite GSI (hash + range) to an existing table source:173
- UpdateTable - add GSI adds a GSI with KEYS_ONLY projection source:212
- UpdateTable - add GSI adds a GSI with INCLUDE projection and NonKeyAttributes source:243
- UpdateTable - add GSI can query a newly created GSI after putting items source:316
- UpdateTable - add GSI adds multiple GSIs sequentially source:367
- UpdateTable - add GSI accepts a conflicting redeclaration of an existing key attribute and keeps the stored type source:454
- UpdateTable - add GSI drops an unused AttributeDefinition supplied with a GSI add source:525
- UpdateTable - remove GSI removes a GSI from a table source:601
- UpdateTable - GSI validation rejects removing a non-existent GSI source:774
-
createTable Tier 1 7 diverging
View these tests in the suite →- CreateTable - validation rejects a GSI INCLUDE projection without NonKeyAttributes source:265
- CreateTable - validation rejects StreamSpecification with StreamEnabled false plus a StreamViewType source:291
- CreateTable - configuration parameters DeletionProtectionEnabled round-trips source:38
- CreateTable - configuration parameters TableClass STANDARD_INFREQUENT_ACCESS round-trips source:50
- CreateTable - configuration parameters SSESpecification with the AWS-managed key round-trips source:61
- CreateTable - configuration parameters OnDemandThroughput round-trips on a PAY_PER_REQUEST table source:76
- CreateTable - LSI rejects an LSI INCLUDE projection without NonKeyAttributes source:117
-
scan Tier 1 6 diverging
View these tests in the suite →- Scan - Select / ProjectionExpression rejections Select ALL_ATTRIBUTES with ProjectionExpression is rejected source:72
- Scan - Select / ProjectionExpression rejections Select ALL_PROJECTED_ATTRIBUTES without an IndexName is rejected source:87
- Scan - Select / ProjectionExpression rejections Select COUNT with ProjectionExpression is rejected source:101
- Scan - Select / ProjectionExpression rejections Select ALL_PROJECTED_ATTRIBUTES with ProjectionExpression and no IndexName is rejected source:117
- Scan - Select / ProjectionExpression rejections Select SPECIFIC_ATTRIBUTES without ProjectionExpression is rejected source:134
- Scan - validation rejects TotalSegments above the maximum source:22
-
query Tier 1 5 diverging
View these tests in the suite →- Query - Select SPECIFIC_ATTRIBUTES Select SPECIFIC_ATTRIBUTES without ProjectionExpression is rejected source:121
- Query - Select / ProjectionExpression rejections Select ALL_ATTRIBUTES with ProjectionExpression is rejected source:141
- Query - Select / ProjectionExpression rejections Select ALL_PROJECTED_ATTRIBUTES without an IndexName is rejected source:159
- Query - Select / ProjectionExpression rejections Select COUNT with ProjectionExpression is rejected source:176
- Query - Select / ProjectionExpression rejections Select ALL_PROJECTED_ATTRIBUTES with ProjectionExpression and no IndexName is rejected source:195
-
updateTable Tier 1 5 diverging
View these tests in the suite →- UpdateTable - configuration parameters UpdateTable enables DeletionProtectionEnabled source:47
- UpdateTable - configuration parameters UpdateTable changes TableClass source:57
- UpdateTable - configuration parameters UpdateTable changes OnDemandThroughput source:72
- DeleteTable - deletion protection enforcement rejects DeleteTable while deletion protection is enabled source:106
- DeleteTable - deletion protection enforcement allows DeleteTable after protection is disabled source:125
-
ttl Tier 2 5 diverging
View these tests in the suite →- TTL - basic enables TTL on a table source:45
- TTL - basic DescribeTimeToLive returns ENABLED status and correct attribute name after enabling source:65
- TTL - basic enables TTL with a different attribute name source:104
- TTL - validation rejects empty attribute name source:140
- TTL - validation rejects UpdateTimeToLive on non-existent table source:156
-
updateItem Tier 1 2 diverging
View these tests in the suite →- UpdateItem - ReturnValues granularity REMOVE with UPDATED_NEW omits Attributes (nothing was set to a new value) source:982
- UpdateItem - ConditionExpression ReturnValuesOnConditionCheckFailure ALL_OLD returns existing item on failure source:271
-
tags Tier 2 2 diverging
View these tests in the suite →- Tags - validation rejects TagResource with an invalid ARN format source:188
- Tags - validation rejects ListTagsOfResource with a non-existent ARN source:211
-
batchWriteItem Tier 1 1 diverging
View these tests in the suite →- BatchWriteItem - index key validation rejects an empty-string index key value source:58
-
legacy-api Tier 3 1 diverging
View these tests in the suite →- Legacy API - KeyConditions and QueryFilter QueryFilter with ComparisonOperator EQ on a BOOL attribute filters correctly source:225
What it doesn't attempt
Operations Dynalite declines rather than gets wrong, so none of this counts towards its divergence. It is what the gap in its 68.6% coverage is made of. Each test here skipped itself because the target's own feature probe said the operation isn't implemented, which is often a deliberate choice rather than a defect.
-
partiql Tier 2 none of it 186 not attempted
View these tests in the suite →- BatchExecuteStatement - PartiQL batch of multiple SELECT statements
- BatchExecuteStatement - PartiQL batch of INSERT and UPDATE statements
- BatchExecuteStatement - PartiQL partial failure - one valid and one invalid statement
- BatchExecuteStatement - PartiQL honours a RETURNING clause on a member statement
- BatchExecuteStatement - PartiQL honours a RETURNING ALL NEW * clause on a member UPDATE
- BatchExecuteStatement - PartiQL honours a RETURNING MODIFIED NEW * clause on a member UPDATE (only the changed attr)
- BatchExecuteStatement - PartiQL omits Item when a member UPDATE produces an empty MODIFIED projection
- BatchExecuteStatement - PartiQL surfaces an invalid RETURNING variant on a member DELETE as a per-statement error
- BatchExecuteStatement - PartiQL surfaces a malformed member statement as a per-statement ValidationError without failing the batch
- BatchExecuteStatement - PartiQL rejects an empty Statements array
- BatchExecuteStatement - PartiQL ConsistentRead is honoured per member charges a small eventually-consistent read half a unit
- BatchExecuteStatement - PartiQL ConsistentRead is honoured per member charges exactly twice that when the member asks for consistency
- BatchExecuteStatement - PartiQL ConsistentRead is honoured per member treats an explicit false the same as omitting it
- BatchExecuteStatement - PartiQL ConsistentRead is honoured per member rates each member of a mixed batch on its own setting
- BatchExecuteStatement - PartiQL a batch SELECT must name the table primary key rejects a member that filters on a non-key attribute
- BatchExecuteStatement - PartiQL a batch SELECT must name the table primary key rejects an index-qualified member naming the index key
- BatchExecuteStatement - PartiQL a batch SELECT must name the table primary key rejects one naming both the table primary key and the index key
- BatchExecuteStatement - PartiQL a batch SELECT must name the table primary key leaves the rest of the batch running
- BatchExecuteStatement - PartiQL a failed member echoes its table only if it ran carries TableName on a conditional failure
- BatchExecuteStatement - PartiQL a failed member echoes its table only if it ran carries TableName on a duplicate insert
- BatchExecuteStatement - PartiQL a failed member echoes its table only if it ran omits TableName on a member rejected before it ran
- BatchExecuteStatement - PartiQL ReturnValuesOnConditionCheckFailure on a batch member returns no Item with the option set to ALL_OLD
- BatchExecuteStatement - PartiQL ReturnValuesOnConditionCheckFailure on a batch member returns no Item with the option set to NONE
- BatchExecuteStatement - PartiQL ReturnValuesOnConditionCheckFailure on a batch member returns no Item with the option set to undefined
- BatchExecuteStatement - PartiQL ReturnValuesOnConditionCheckFailure on a batch member does return the item on a TransactWriteItems ConditionCheck
- ExecuteStatement - comparison on non-scalar types 'SS' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'SS' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'SS' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'SS' matches a permuted value, because a string set is unordered
- ExecuteStatement - comparison on non-scalar types 'SS' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'NS' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'NS' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'NS' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'NS' matches a permuted value, because a number set is unordered
- ExecuteStatement - comparison on non-scalar types 'NS' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'BS' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'BS' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'BS' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'BS' matches a permuted value, because a binary set is unordered
- ExecuteStatement - comparison on non-scalar types 'BS' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'L' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'L' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'L' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'L' does not match a permuted value, because a list is ordered, so a permutation is a different value
- ExecuteStatement - comparison on non-scalar types 'L' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'M' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'M' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'M' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'M' matches a permuted value, because a map compares by content, not by the order its keys arrived in
- ExecuteStatement - comparison on non-scalar types 'M' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'B' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'B' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'B' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'B' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types 'NULL' matches an equal value
- ExecuteStatement - comparison on non-scalar types 'NULL' does not match a different value
- ExecuteStatement - comparison on non-scalar types 'NULL' answers <> as the complement of =
- ExecuteStatement - comparison on non-scalar types 'NULL' agrees with the same predicate as a ConditionExpression
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against BOOL
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against NULL
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against L
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against M
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against SS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against NS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering rejects < against BS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering names the operator < as written
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering names the operator <= as written
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering names the operator > as written
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering names the operator >= as written
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering names BETWEEN as written too
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against BOOL
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against NULL
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against L
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against M
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against SS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against NS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts = and <> against BS
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering accepts an ordering comparison between S and N
- ExecuteStatement - comparison on non-scalar types ordering operators reject an operand type with no ordering orders binary by its bytes
- ExecuteStatement - comparison on non-scalar types a write conditioned on a non-scalar predicate fires when the predicate holds
- ExecuteStatement - comparison on non-scalar types a write conditioned on a non-scalar predicate raises ConditionalCheckFailed and leaves the item when it does not
- ExecuteStatement - PartiQL INSERTs a new item
- ExecuteStatement - PartiQL SELECTs an item by primary key
- ExecuteStatement - PartiQL SELECTs with WHERE clause using comparison
- ExecuteStatement - PartiQL UPDATEs an existing item
- ExecuteStatement - PartiQL DELETEs an item
- ExecuteStatement - PartiQL rejects INSERT on an existing item (INSERT is not upsert)
- ExecuteStatement - PartiQL INSERT succeeds after DELETE of same key
- ExecuteStatement - PartiQL SELECT returns empty results for non-matching WHERE
- ExecuteStatement - PartiQL parameterized INSERT with ? placeholders
- ExecuteStatement - PartiQL parameterized SELECT with ? placeholder
- ExecuteStatement - PartiQL SELECT with nested map path
- ExecuteStatement - PartiQL SELECT with specific attributes
- ExecuteStatement - PartiQL SELECT with begins_with in WHERE clause
- ExecuteStatement - PartiQL PartiQL UPDATE with SET on attribute
- ExecuteStatement - PartiQL PartiQL UPDATE with REMOVE
- ExecuteStatement - PartiQL returns a populated ConsumedCapacity block when requested
- ExecuteStatement - PartiQL evaluates negated predicates (NOT begins_with, IS NOT MISSING)
- ExecuteStatement - PartiQL DELETE with a false non-key predicate fails ConditionalCheckFailed and leaves the item
- ExecuteStatement - PartiQL DELETE with a true non-key predicate removes the item
- ExecuteStatement - PartiQL UPDATE with a false non-key predicate fails ConditionalCheckFailed and leaves the item
- ExecuteStatement - PartiQL UPDATE with a true non-key predicate mutates the item
- ExecuteStatement - PartiQL DELETE with a false NOT begins_with predicate fails ConditionalCheckFailed
- ExecuteStatement - PartiQL DELETE with a true NOT begins_with predicate removes the item
- ExecuteStatement - PartiQL rejects a write WHERE clause that omits the primary key
- ExecuteStatement - PartiQL DELETE on a missing key with a non-key predicate is a silent no-op
- ExecuteStatement - PartiQL DELETE RETURNING ALL OLD * returns the deleted item
- ExecuteStatement - PartiQL DELETE RETURNING ALL OLD * on a missing item returns an empty Items list
- ExecuteStatement - PartiQL DELETE rejects RETURNING MODIFIED OLD * (only ALL OLD * is valid on DELETE)
- ExecuteStatement - PartiQL DELETE rejects RETURNING MODIFIED NEW * (only ALL OLD * is valid on DELETE)
- ExecuteStatement - PartiQL DELETE rejects RETURNING ALL NEW * with a 400, not a 500
- ExecuteStatement - PartiQL UPDATE RETURNING ALL OLD * returns the full prior item
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * returns only the changed attribute (old value, no key)
- ExecuteStatement - PartiQL UPDATE RETURNING ALL NEW * returns the full new item
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * returns only the changed attribute (new value, no key)
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * over a nested path returns only the changed leaf
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * over a nested path returns only the changed leaf at its old value
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED OLD * returns the removed attribute at its old value
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED NEW * returns an empty Items list
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * on a newly-set attribute returns an empty Items list
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * on a newly-set attribute returns the new value
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * on a list index returns only the changed element
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * on a list index returns only the prior element
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * on a non-zero list index returns only the changed element
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * on a non-zero list index returns the prior element
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * over multiple list indices returns a dense pack of the changed elements
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * over multiple list indices returns the prior elements densely
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * packs changed indices in ascending index order, not statement order
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * packs changed indices in ascending index order, not statement order
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * on an out-of-range list index (append) returns an empty Items list
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * on an out-of-range list index (append) returns an empty Items list
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED NEW * appending at exactly the list length returns the appended element
- ExecuteStatement - PartiQL UPDATE RETURNING MODIFIED OLD * appending at exactly the list length returns an empty Items list
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED OLD * on a list index returns the removed element at its old value
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED NEW * on a list index returns the shifted element, not an empty list
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED NEW * on the last list index returns an empty Items list
- ExecuteStatement - PartiQL UPDATE REMOVE RETURNING MODIFIED OLD * on the last list index returns the removed element
- ExecuteStatement - PartiQL UPDATE SET on a list index of an absent attribute is rejected, not auto-created
- ExecuteStatement - PartiQL UPDATE on a non-existent key fails ConditionalCheckFailed (PartiQL UPDATE is not an upsert)
- ExecuteStatement - PartiQL rejects a statement with syntax error
- ExecuteStatement - PartiQL rejects a reference to a non-existent table
- ExecuteTransaction - PartiQL transactional INSERT and UPDATE both succeed atomically
- ExecuteTransaction - PartiQL transaction rolls back on duplicate key INSERT
- ExecuteTransaction - PartiQL multiple INSERTs in one transaction
- ExecuteTransaction - PartiQL idempotent replay under the same ClientRequestToken does not double-apply
- ExecuteTransaction - PartiQL rejects a RETURNING clause inside a transaction statement
- ExecuteTransaction - PartiQL rejects empty TransactStatements
- ExecuteStatement - index qualifier membership a qualified SELECT omits an item the index does not hold
- ExecuteStatement - index qualifier projection follows the index, not the item a KEYS_ONLY GSI returns the index key and the table key and nothing else
- ExecuteStatement - index qualifier projection follows the index, not the item an INCLUDE GSI adds the named attribute and no others
- ExecuteStatement - index qualifier projection follows the index, not the item a KEYS_ONLY LSI returns the index key and the table key and nothing else
- ExecuteStatement - index qualifier projection follows the index, not the item SELECT * against a non-ALL index does not reach back
- ExecuteStatement - index qualifier the reach-back splits by index kind an LSI serves an unprojected attribute from the base table
- ExecuteStatement - index qualifier the reach-back splits by index kind a GSI rejects an unprojected attribute rather than reaching back
- ExecuteStatement - index qualifier the reach-back splits by index kind naming only projected attributes on an LSI charges no table arm
- ExecuteStatement - index qualifier the reach-back splits by index kind a filtered reach-back is charged on rows walked, not rows kept
- ExecuteStatement - index qualifier the reach-back splits by index kind a bounded reach-back walks fewer rows and is charged less
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects a keyed GSI read filtering on an unprojected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects the LSI mirror, so the rule is not about index kind
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts the same GSI filter unkeyed, matching nothing
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts the same LSI filter unkeyed, matching nothing
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts two unprojected filters with no index key
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts a keyed read filtering on an attribute the index does project
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects a keyed read with IS MISSING on an unprojected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects a keyed read with IS NOT MISSING on an unprojected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects a keyed read with begins_with on an unprojected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts the same predicate on a projected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition rejects a keyed read with a negated filter on an unprojected attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition matches every index row when the negated filter names an absent attribute
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition counts IN on the index partition key as keyed
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition accepts an unprojected filter inside an OR branch
- ExecuteStatement - index qualifier the unprojected-filter rejection turns on the key condition counts BETWEEN on the index sort key as keyed
- ExecuteStatement - index qualifier pagination across a qualified read mints a token when a bounded read leaves rows behind
- ExecuteStatement - index qualifier pagination across a qualified read rejects a token minted against one index and replayed against another
- ExecuteStatement - index qualifier write statements reject the qualifier, and not all the same way rejects an INSERT carrying a qualifier at parse position
- ExecuteStatement - index qualifier write statements reject the qualifier, and not all the same way rejects an INSERT whose qualifier names no index with the same message
- ExecuteStatement - index qualifier write statements reject the qualifier, and not all the same way rejects an UPDATE carrying a qualifier semantically
- ExecuteStatement - index qualifier write statements reject the qualifier, and not all the same way rejects a DELETE carrying a qualifier semantically
- ExecuteStatement - index qualifier write statements reject the qualifier, and not all the same way leaves the rows untouched after the rejected writes
- ExecuteStatement - index qualifier a transaction refuses an index-qualified read rejects it outright, not as a cancellation
- ExecuteStatement - index qualifier a transaction refuses an index-qualified read accepts the same read unqualified
- ExecuteStatement - index qualifier capacity lands on the index arm a keyed GSI read charges the index and a zero table arm
- ExecuteStatement - index qualifier capacity lands on the index arm a keyed LSI read charges the index and a zero table arm
- ExecuteStatement - index qualifier capacity lands on the index arm ConsistentRead doubles the LSI arm
- ExecuteStatement - index qualifier capacity lands on the index arm ConsistentRead doubles both arms of a reach-back
- ExecuteStatement - index qualifier capacity lands on the index arm rejects ConsistentRead against a GSI qualifier
-
vectorSearch Tier 2 none of it 36 not attempted
View these tests in the suite →- SearchVectors - ConsumedCapacity shape reports VectorSearchRequestBytes with no classic capacity fields
- SearchVectors - ConsumedCapacity shape reports the same shape under INDEXES as under TOTAL
- SearchVectors - ConsumedCapacity shape reports nothing under NONE
- PutItem - vector write capacity shape INDEXES adds a per-index VectorWriteRequestBytes map beside the classic fields
- PutItem - vector write capacity shape TOTAL folds nothing in: no vector fields at all
- PutItem - vector write capacity shape a write not touching the vector attribute reports no vector write
- PutItem - vector write capacity shape an identical overwrite reports no vector write: replication is delta-based
- PutItem - a vector index is charged on the change to its stored view charges the index that projects the changed attribute, and not the one that does not
- PutItem - a vector index is charged on the change to its stored view charges neither when the write changes nothing either index holds
- PutItem - VectorWriteRequestBytes reports the 1024 floor for an entry below it on every term
- PutItem - VectorWriteRequestBytes applies the floor per index, not per write
- PutItem - VectorWriteRequestBytes charges four bytes per dimension
- PutItem - VectorWriteRequestBytes charges the vector attribute’s name by its own length
- PutItem - VectorWriteRequestBytes charges a projected non-vector attribute its own item size
- CreateTable - vector index lifecycle walks CREATING to ACTIVE and describes the index faithfully
- CreateTable - vector index lifecycle round-trips a SearchSchema of HASH and INLINE_FILTER elements
- CreateTable - vector index lifecycle accepts the 4096-dimension boundary
- SearchVectors - index readiness after CreateTable rejects retryably between ACTIVE and the first served search
- PartiQL - vector indexes are out of reach rejects a PartiQL read of a vector index
- PartiQL - vector indexes are out of reach reads the vector attribute off the base table like any other item
- SearchVectors - deterministic search behaviour COSINE: identical vector scores 0, opposite scores 2, lower is closer
- SearchVectors - deterministic search behaviour EUCLIDEAN: identical vector scores 0, straight-line distance otherwise
- SearchVectors - deterministic search behaviour DOT_PRODUCT: higher is closer and scores can be negative
- SearchVectors - deterministic search behaviour returns the identical vector as the top match
- SearchVectors - deterministic search behaviour omits the vector attribute by default and returns it when projected
- SearchVectors - deterministic search behaviour caps results at the item count with no pagination surface
- SearchVectors - deterministic search behaviour stores full precision on the base table and f32 in the index
- UpdateTable - vector index lifecycle adds an index that backfills like a GSI, enforces one online action, then deletes it
- UpdateTable - vector index lifecycle refuses to delete the table while a vector index is still being created
- UpdateTable - vector index lifecycle reports UPDATING with Backfilling false while allocating, and takes a cancel only once backfilling starts
- CreateTable - vector index request validation rejects Dimensions of 0 at the request model layer
- CreateTable - vector index request validation rejects an index name shorter than 3 characters
- SearchVectors - request validation rejects TopK of 0 at the request model layer
- SearchVectors - request validation rejects a search against an index the table does not have
- PutItem - vector index write validation accepts a write missing the HASH attribute but leaves it unreachable through that index
- PutItem - vector index write validation removes an item from the index when its vector attribute is removed
-
streams Tier 2 none of it 18 not attempted
View these tests in the suite →- DynamoDB Streams - basic table with StreamSpecification has LatestStreamArn in DescribeTable
- DynamoDB Streams - basic table StreamSpecification.StreamEnabled is true
- DynamoDB Streams - basic table StreamSpecification.StreamViewType matches what was requested
- DynamoDB Streams - basic ListStreams returns the stream for our table
- DynamoDB Streams - basic ListStreams with TableName filter returns only our table's stream
- DynamoDB Streams - basic DescribeStream returns stream status ENABLED or ENABLING
- DynamoDB Streams - basic DescribeStream returns at least one shard
- DynamoDB Streams - basic each shard has a ShardId
- DynamoDB Streams - basic TRIM_HORIZON returns a valid iterator string
- DynamoDB Streams - basic LATEST returns a valid iterator string
- DynamoDB Streams - basic GetRecords after PutItem contains the new image (INSERT event)
- DynamoDB Streams - basic INSERT record has eventName INSERT
- DynamoDB Streams - basic INSERT record dynamodb.Keys contains the item key
- DynamoDB Streams - basic INSERT record dynamodb.NewImage contains the full item
- DynamoDB Streams - basic GetRecords after UpdateItem contains both old and new images (MODIFY event)
- DynamoDB Streams - basic GetRecords after DeleteItem contains old image (REMOVE event)
- DynamoDB Streams - basic NEW_IMAGE view type records have NewImage but no OldImage on MODIFY
- DynamoDB Streams - basic KEYS_ONLY view type records have Keys but no NewImage or OldImage
-
backups Tier 2 none of it 5 not attempted
View these tests in the suite →- Continuous backups - PITR reports PITR DISABLED by default
- Continuous backups - PITR enabling PITR transitions PointInTimeRecoveryStatus to ENABLED
- On-demand backups - lifecycle and restore CreateBackup → DescribeBackup → ListBackups → DeleteBackup
- On-demand backups - lifecycle and restore RestoreTableFromBackup initiates a restore into a new table
- On-demand backups - lifecycle and restore DescribeBackup on a deleted backup throws BackupNotFoundException
-
account Tier 2 none of it 2 not attempted
View these tests in the suite →- Account reads - DescribeLimits, DescribeEndpoints DescribeLimits returns positive account and table capacity limits
- Account reads - DescribeLimits, DescribeEndpoints DescribeEndpoints returns at least one endpoint with an address
-
contributorInsights Tier 2 none of it 2 not attempted
View these tests in the suite →- Contributor insights - enable/describe/list reports DISABLED by default
- Contributor insights - enable/describe/list enabling transitions the status and lists the table
-
export Tier 2 none of it 2 not attempted
View these tests in the suite →- Export and import - S3 ExportTableToPointInTime initiates an export and reports it
- Export and import - S3 ImportTable ingests S3 data into a new table
-
resourcePolicy Tier 2 none of it 2 not attempted
View these tests in the suite →- Resource policies - Put/Get/Delete GetResourcePolicy on a table with no policy throws PolicyNotFoundException
- Resource policies - Put/Get/Delete Put then Get round-trips the policy, and Delete removes it
-
kinesis Tier 2 none of it 1 not attempted
View these tests in the suite →- Kinesis streaming destination enables a streaming destination and reports it via Describe
Run history
Every percentage here is divergence, per tier and over the whole suite, so lower is better in each column. Coverage is the exception it is named as.
| Run | Gradecurrent criteria | Divergence | Movement |
|---|---|---|---|
| Grade C | 10.7% | unchanged | |
|
Suite on 3.6.0 was cut but never published. eu-west-2 changed how it validates TransactWriteItems while the 3.6.0 measurement was running, so five tests failed against DynamoDB itself and no board was produced. This release carries the fix, and the changes listed under 3.6.0 are first measured here. eu-north-1 and ap-northeast-2 made the change first, and eu-west-2 followed on 2026-10-08, between two runs on main 30 minutes apart. The three now check a transaction's request before running it. An empty TransactItems gets the validation framework's generic constraint message. A 32-level value in the request is refused with a top-level ValidationException, where the transaction used to cancel on it or go on to evaluate the condition. A transacted Update that UpdateItem's statement-sized rule refuses is refused the same way, where it used to be stored. The other 30 regions still answer as before. The five tests accept either answer, exactly, until the regions settle. No engine loses a test over it, and on the 3.5.0 board's results the engines that already refuse a 32-level value up front pass tests they used to fail: three for LocalStack, and one each for DynamoDB Local, ExtendDB and ExtendDB (SQLite). The tests keep their names, which describe what the 30 regions do, until one answer is pinned, because a rename needs every committed results file re-run. The board and the results table now sort by grade, best first, and rows sharing a grade by the effective figure the letter is read from. They used to sort on divergence alone, and coverage lowers a letter without moving a row, so a target diverging slightly less over much less of the suite could sit above a better-graded one. No grade or figure changes. |
Grade C | 10.7% | unchanged |
|
Suite on Five Scan error messages are now regional splits. The validation-framework
rollout reached Scan's parameter checks in September, and eu-west-2,
eu-central-1, us-west-1 and ap-northeast-2 now word the errors for The negative The nesting-depth row moves af-south-1, ap-southeast-3, ap-southeast-4, ap-southeast-5 and il-central-1 to the strict side, leaving 22 regions strict and 11 lax. ap-northeast-1 answers both ways and stays lax for now. UpdateItem's item size is now a regional split, across eleven tests. Twenty-two regions, eu-west-2 among them, size an update by what the statement writes, as the suite already pinned, while ten cap the finished item at 409,600 like any other write. Engines that apply the plain cap are credited in those ten. Fourteen cases from @exoego for the 4096-byte expression cap and the 32-level nesting cap on the batch and transact write surfaces, captured against eu-west-2 and us-east-1.
|
Grade C | 10.7% | diverged 0.8 percentage points less |
|
Suite on Kumo joins the board, suggested by @exoego. It is a Go emulator covering 82 AWS services, of which DynamoDB is one, and it runs from a container image or a single binary with nothing else to install. The board's separate support and capability pages are now one emulator directory, with each project's feature and operation support in a single entry. |
Grade C | 11.5% | unchanged |
| Grade C | 11.5% | unchanged | |
|
Suite on Thirteen captures against eu-west-2 turned into coverage, and the suite grew from 1056 tests to 1251. All of it was ground truth nothing asserted, so an engine could discard a PartiQL index qualifier or store an item AWS would refuse and still score a clean pass.
Two fixes came with it. A local run against real DynamoDB takes its own table
namespace, so it can no longer delete a CI run's tables. And a
The over-25-requests assertion beside it spans both cohorts instead of becoming a second row. Neither wording is byte-stable: the table name carries a per-run suffix, the old cohort echoes all 26 requests back, and seven regions echo them as a JVM object identity rather than expanded fields. A row records one verbatim answer per region and there is nothing verbatim here to record, so the anchored pattern grew a second branch instead. It still refuses a wrong limit and a wrong table, and it matches every one of the 33 answering regions. The capture harness can take that evidence without creating tables. |
Grade C | 11.5% | diverged 1.3 percentage points less |
| Grade C | 12.8% | unchanged | |
| Grade C | 12.8% | unchanged | |
| Grade C | 12.8% | unchanged | |
|
Suite on AWS corrected the vector index readiness documentation, prompted by a write-up of the earlier guidance that drew on the suite's measurements. The ACTIVE-plus-backfilling state the old advice was built around, and which no index ever occupies, is gone from the three pages that described it. The wait now reads "Backfilling is not true" rather than "is false", so a check written literally from it fires on both creation paths instead of neither. The tutorial no longer says a search during backfill can return incomplete results. Two things the suite had measured but nobody had written down are documented as well: that DescribeTable reporting ACTIVE leads the dedicated search endpoint, and that the readiness check depending on neither status field is a real search in a retry loop. That contract is now pinned rather than described. The UpdateTable walk asserts that Backfilling true is only ever reported alongside CREATING, that an ACTIVE index reports no Backfilling field at all, and that the base table goes ACTIVE while the index is still building, which is what makes a table waiter the wrong gate for a search. The first search that succeeds has to carry every seeded item, since the backfill window answers with an error rather than a partial view. On the CreateTable path a new test runs the documented check the way an application would, and every rejection before the first served response has to be the retryable ValidationException rather than a not-found. The suite's own search wait now absorbs those two rejections and rethrows every other answer, so a fixture waiting on an index that is ACTIVE but not yet served no longer fails on the lag it was waiting out. Two files asserting exact rejection messages wait for a served search rather than for ACTIVE: "does not have the specified index" is also what a freshly ACTIVE index says, and it would otherwise stand in for whichever message the case asked for. The tutorial's other new claim, that a table cannot be deleted while a vector index is being created, has a test of its own. Only the UpdateTable path can ask it. Across three runs an index created with its table reached ACTIVE in the same 250ms poll as the table, so the table is never ACTIVE with the index still building there, and a DeleteTable during creation is refused for the table's own status rather than with the documented index wording. Adding an index to a live table opens that window about thirty seconds in. The test cancels the index afterwards instead of waiting out the backfill, which a still-creating vector index turns out to accept the way a backfilling GSI does, so it costs a minute rather than seventeen. A release now dispatches its measurement as the results bot rather than with
the workflow's own token. GitHub raises no |
Grade C | 12.8% | unchanged |
|
Suite on The board now measures the most recent release tag rather than Every board now says what produced it. A board is graded against the suite manifest and split registry as they stood at the ref it measured. Region health is the exception and is read live, so a region dropped since the tag still counts against today's cohorts. That is the one input allowed to move under a board without a new measurement, and the board carries a health date beside its measurement date to say so. Releases are cut by one workflow dispatch: it bumps the version, dates this section, installs against the bumped tree, tags, and opens a draft release, then starts the measurement. The draft publishes itself when the board carrying that version lands, which takes about three hours. eu-west-2 has crossed to the validation framework's generic constraint message
for The matching validation-ordering row is retired. Both wordings refuse an empty
A probe absent from the baseline is no longer reported as drift. Adding a probe to the capture script leaves every older baseline without it, and a scheduled red then named the new probe as the thing that had moved. The weekly cross-region capture now includes eu-west-2, so the drift lens reads its baseline and the candidate regions from one capture taken at one moment rather than comparing today's candidates against an older baseline file. A scheduled red also keeps the eu-west-2 capture its drift verdict was read from, which was previously discarded with the runner. |
Grade C | 12.8% | unchanged |
| Grade C | 12.8% | unchanged | |
|
Suite on ExtendDB's SQLite backend joins the run, built from the same release as the PostgreSQL one and held to the same TLS, SigV4 and IAM posture, so the storage engine is the only thing that differs between them. A project's other builds now sit behind a disclosure on its row. Every build is measured in full and has a row of its own with its own figures; the disclosure starts closed only when every build under it reads the same grade, divergence and coverage as the row above, and only when each of them was measured in that run: a carried row on either side opens it, and so does a run the suite declined to score. It is read from each run, so a build can start closed on one and open on the next. The README table has no disclosure to offer, so it lists every build outright. Every target in the data endpoints gains two fields.
The |
Grade C | 12.8% | diverged 0.2 percentage points less |
| Grade C | 13.0% | diverged 0.7 percentage points more | |
|
Suite on Read this first if you consume the JSON. The data endpoints go from schema 2 to schema 4 in one step. Schema 3 was never published on its own, so everything on 2 crosses both steps at once. Schema 3 breaks in four ways:
Schema 4 is additive on top: each target carries its grade and the full criteria
in A score is two figures, never oneDivergence is the share of the whole suite a target answers differently from real DynamoDB. Coverage is the share it implements at all. They are reported apart and never summed, because a declined operation is discoverable in minutes and a wrong one in production. No target was re-run for the change and no pass, fail or skip moved: what changed is how the same counts are expressed. Everything else that was a percentage followed the headline down - tier figures, the per-region drilldown, the per-operation table, and the colour bands, which inverted with them. A target's history is two plots rather than one, because divergence falls when a target stops attempting something it used to get wrong, so a divergence line alone can render a withdrawal as an improvement. Every target wears a letterDivergence sets it - A under 5%, B under 15%, C under 25%, D under 35%, F beyond
These are grading criteria version 1, dated in the methodology, which carries the derivation. Where a threshold sits is a hand-picked input to a published letter, and moving one regrades targets whose results never changed, so any change to a band, the coverage weight or the A+ gate bumps the version. The suite grows from 998 tests to 1054Vector search (#125). 42 tests over the deterministic surface DynamoDB
shipped in August 2026: the index lifecycle on both creation paths, request
validation on each plane, rejection wording, write-path validation, search on a
fixture where the nearest neighbour is unambiguous, the two new capacity shapes,
and PartiQL's inability to reach a vector index. Every pinned value was
characterised against real DynamoDB in eu-west-2 before it was asserted. Two
findings worth naming: searching during a backfill is an error, which settles
which side of a contradiction in AWS's own documentation is right - three
developer-guide pages say the call fails, the tutorial page says results can be
incomplete - and an overwrite leaving the stored vector unchanged reports no
vector write capacity at all, because index replication is delta-based. Both
sides are captured in Index write costs (#124). 14 tests. The suite's only per-index capacity assertion was on a Query, so the write side - the half you get billed extra for - went unmeasured. A sub-1KB write costs one unit for the table and one for each index it lands in, and LSI units fold into the total exactly as GSI units do. Moving an item to a new GSI key costs two on that index, a delete and an insert; touching a projected attribute costs one; touching a non-projected attribute costs nothing, and the response carries no arm for that index rather than a zero. An overwrite that leaves the item unchanged reports no index cost whatsoever. The index exclusions create no indexed table (#116). Corrections
|
Grade C | 12.3% | diverged 0.2 percentage points less |
| Grade C | 12.5% | diverged 0.2 percentage points more | |
| Grade C | 12.3% | unchanged | |
| Grade C | 12.3% | unchanged | |
| Grade C | 12.3% | unchanged | |
| Grade C | 12.3% | unchanged | |
| Grade C | 12.3% | diverged 9.0 percentage points less | |
| Grade D | 21.3% | diverged 0.1 percentage points less | |
|
Suite on Grew to 982 tests, up 28, all characterised against real DynamoDB across the per-region ground truth 2.0.0 put in place. New coverage is PartiQL's RETURNING clause; the GSI lifecycle also joins the ground truth, and the sweep's drift classifier gains a converged case.
|
Grade C | 21.5% | diverged 0.6 percentage points less |
| Grade C | 22.1% | unchanged |
Showing the 24 most recent runs. The chart above covers the full history, and every run is browsable from Runs.