Skip to content

Feature: Support DynamoDB condition expressions and update expressions in generated mutations #3390

Description

@cheruvian

Describe the feature you'd like to request

Support for DynamoDB's full expression capabilities in generated GraphQL mutations:

  1. Condition expressions - The GraphQL mutations already accept condition: Model*ConditionInput, but this only covers basic field comparisons. Advanced conditions like attribute_not_exists(), combined with update logic, aren't fully supported.

  2. Update expressions - Currently all updates use simple SET field = :value. DynamoDB supports much richer update semantics:

    • ADD for atomic counter increment/decrement and set operations
    • SET field = field + :value for relative updates
    • SET field = if_not_exists(field, :default) for initialization
    • SET field = list_append(field, :items) for atomic list operations
    • REMOVE field conditionally

These patterns are essential for concurrent-safe operations like counters, rate limiting, inventory management, and state machines.

Describe the solution you'd like

Option A: Dedicated counter/atomic field types (recommended for common cases)

An opt-in field modifier for the most common use case - atomic counters:

const schema = a.schema({
  Post: a.model({
    id: a.id(),
    title: a.string(),
    viewCount: a.integer().counter(),  // or a.counter()
  })
});

Generates:

input UpdatePostInput {
  id: ID!
  title: String
  viewCount: Int
  viewCount_increment: Int  # Atomic ADD operation
}

Option B: Expression-level escape hatch (for advanced cases)

For complex expressions that don't fit a predefined pattern, allow passing update expression components:

mutation {
  updatePost(
    input: { id: "123" }
    updateExpression: {
      set: [{ field: "viewCount", expression: "if_not_exists(viewCount, :zero) + :inc" }]
      expressionValues: { ":zero": 0, ":inc": 1 }
    }
    condition: { viewCount: { lt: 100 } }
  ) {
    id
    viewCount
  }
}

Option C: Extend condition input for attribute functions

Expand Model*ConditionInput to support:

  • attributeNotExists (exists today but scoped to field)
  • Combining conditions with update operations atomically

Describe alternatives you've considered

  1. Custom VTL/JS resolvers - Works but defeats the purpose of generated APIs
  2. Lambda via @function - Adds latency and infrastructure overhead
  3. Direct DynamoDB SDK - Bypasses Amplify entirely, loses type safety and integrated auth

Additional context

Real-world example - rate limiting with atomic counter:

// What we have to do today (bypassing Amplify):
await docClient.send(new UpdateCommand({
  TableName: tableName,
  Key: { id },
  UpdateExpression: "SET activeCount = if_not_exists(activeCount, :zero) + :inc, updatedAt = :now",
  ConditionExpression: "attribute_not_exists(activeCount) OR activeCount < :limit",
  ExpressionAttributeValues: {
    ":zero": 0,
    ":inc": 1,
    ":limit": 10,
    ":now": new Date().toISOString(),
  },
}));

Implementation note: The VTL resolver generation in packages/amplify-graphql-model-transformer/src/resolvers/dynamodb/mutation.ts already initializes an expAdd bucket (line 50) and has logic to build ADD expressions (lines 100-109), but nothing populates it. Some infrastructure already exists.

Generated client note: The generated TypeScript client (@aws-amplify/data-schema) also doesn't expose the existing condition parameter in update() and delete() methods, even though the underlying GraphQL mutations support it. Full end-to-end support would require changes in both this repo (for update expressions) and amplify-data (for exposing conditions in the client API).

  • 👋 I may be able to implement this feature request
  • ⚠️ This feature might incur a breaking change

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions