Specifies a static ORDER BY for a field. When the field also carries an @orderBy argument and the client supplies a value, the dynamic order wins; otherwise @defaultOrder applies. Without an explicit @defaultOrder, paginated fields default to ascending primary-key order.

SDL signature

directive @defaultOrder(
    index: String,
    fields: [FieldSort!],
    primaryKey: Boolean = false,
    direction: SortDirection = ASC
) on FIELD_DEFINITION

input FieldSort {
    name:    String!
    collate: String
}

enum SortDirection { ASC, DESC }

Parameters

Name Type Default Description

index

String

none

Name of a database index. The generator emits the index’s column list as the sort specification. Requires <includeIndexes>true</includeIndexes> in the jOOQ generator.

fields

[FieldSort!]

none

Explicit column list. Each FieldSort has a required name (the column on the field’s parent table) and an optional collate (database-specific collation).

primaryKey

Boolean

false

When true, sorts by the parent table’s primary key columns in declaration order. Common choice for stable keyset pagination.

direction

SortDirection

ASC

Sort direction applied to every column in the spec. ASC or DESC.

Exactly one of index, fields, or primaryKey must be set.

Canonical example

The example schema’s connection fields default to primary-key order:

type Query {
    stores: [Store!]! @asConnection @defaultOrder(primaryKey: true)

    filmsConnection(
        first: Int, last: Int, after: String, before: String
    ): FilmsConnection! @defaultOrder(primaryKey: true)

    filmsOrderedConnection(
        rating: MpaaRating @field(name: "RATING"),
        order: [FilmOrderBy] @orderBy,
        first: Int, last: Int, after: String, before: String
    ): FilmsConnection! @defaultOrder(primaryKey: true)
}

stores and filmsConnection have no @orderBy argument: every page is sorted by primary key. filmsOrderedConnection accepts a dynamic order argument; when the client omits it, the field falls back to @defaultOrder(primaryKey: true). The keyset-pagination cursor binds to whichever order is active.

Field-based with collation:

type Query {
    customers(first: Int = 100, after: String): CustomerConnection
        @defaultOrder(fields: [
            {name: "LAST_NAME",  collate: "case_insensitive"},
            {name: "FIRST_NAME", collate: "case_insensitive"}
        ])
}

Index-based with descending direction:

type Query {
    films(orderBy: FilmOrder @orderBy, first: Int = 100, after: String): FilmConnection
        @defaultOrder(index: "IDX_TITLE", direction: DESC)
}

Constraints

  • Exactly one of index, fields, or primaryKey must be set. Multiple or none fails the build.

  • Applies to fields only. Apply it to the connection-bearing field, not the synthesised Connection / Edge types.

  • When combined with @orderBy on the same field, the client’s argument value (when present) takes precedence; @defaultOrder is the fallback.

  • direction is global across the spec. Per-column direction requires @orderBy (the enum input carries its own SortDirection).

  • index requires jOOQ index generation. fields[].name resolves against the field’s return-type table, not the parent.

  • Stable keyset pagination depends on the order being deterministic. primaryKey: true is the safe default; field-based orders need a tie-breaker (typically the PK) to avoid unstable cursors.

See also

  • @orderBy supplies the dynamic counterpart.

  • @order reuses the index / fields / primaryKey shape on enum values.

  • @asConnection for connection synthesis; @defaultOrder is required for stable pagination on synthesised connections.

  • How-to: Sort results covers tie-breakers, collation pitfalls, and pagination semantics.