Skip to content

Autogenerated fields available for secondary indexes #630

@mgreiner79

Description

@mgreiner79

Problem

Amplify Data (Gen 2) automatically adds the system fields createdAt and updatedAt to every model and returns them in query results.

However, these fields cannot be referenced in .secondaryIndexes() definitions, because the schema compiler only allows explicitly declared fields.

This prevents developers from using createdAt or updatedAt as sort keys in indexes — a very common pattern (e.g., querying by status ordered by creation time).

Example that fails today:

Report: a
  .model({
    id: a.id(),
    reviewStatus: a.enum(['DRAFT','IN_REVIEW','APPROVED','REJECTED','NEEDS_WORK']).required(),
  })
  .secondaryIndexes((index) => [
    index('reviewStatus')
      .sortKeys(['createdAt']) // ❌ causes InvalidDirectiveError
      .queryField('byReviewStatusAndCreatedAt'')
    }),
  ])

Deployment error:

InvalidDirectiveError: Can't find field 'createdAt' in Substance, 
but it was specified in index 'substancesByReviewStatusAndCreatedAt'.

Solution

Allow the system-managed fields createdAt and updatedAt to be referenced in index definitions.

For example:

.secondaryIndexes((index) => [
  index('reviewStatus')
    .sortKeys(['createdAt'])
    .queryField('byReviewStatusAndCreatedAt')
  }),
])

Alternatives considered

  • Creating a duplicate field (e.g., createdAtCopy: a.datetime()) and populating it manually or via a Lambda trigger so it can be indexed.
    → Works, but is redundant and easy to forget when inserting data.

  • Querying with filters and sorting client-side.
    → Inefficient for large datasets and inconsistent with server-side pagination.

Both alternatives add complexity for something Amplify already tracks internally.

Additional context

  • Amplify Data Gen 2 (@aws-amplify/backend, latest)
  • Deployment via amplify sandbox / amplify push
  • Node.js 20.x (WSL2 + Windows 11)
  • TypeScript schema using a.schema({ ... })

Supporting indexing on system fields would simplify many common models (feeds, review queues, dashboards, audit logs) and remove the need for duplicate “createdAtCopy” fields.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions