Skip to main content
Version: v3.x beta

API Versioning through Field Deprecation

Introduction

As your API evolves to support new features or improved functionality, changes to its existing structure might be required. However, directly altering or removing fields in the API responses can lead to breaking changes.These can disrupt the functionality of client applications that rely on those fields, potentially causing errors or failures in application behavior.

Hasura enables you to easily use the built-in @deprecated schema directive of GraphQL to tag a field as deprecated with an optional reason. This tag allows you to easily mark fields that are no longer valid or those that have been updated as deprecated with a note alerting your consumers to the change.

As an example, imagine we have a type Car with an existing field named engine which is deprecated in favor of motor:

type Car {
id: ID!
make: String!
model: String!
engine: EngineSpec @deprecated(reason: "Use field 'motor' instead")
motor: MotorSpec
}

Consumers of our API will know that engine has been deprecated, why we've deprecated it, and which field to use in its place.

Learn more

You can learn more about this directive in the spec.

Using Field Deprecation in DDN Modeling

The following metadata objects have field deprecation in their GraphQL configuration.

Model

The following example shows how to deprecate a field in a model:

kind: Model
version: V1
definition:
name: Cars
objectType: Car
orderableFields:
- Id
graphql:
selectUniques:
- queryRootField: selectCar
uniqueIdentifier:
- make
- model
deprecated:
reason: Use selectCarById instead
- queryRootField: selectCarById
uniqueIdentifier:
- Id

And the resulting schema:

type Query {
selectCar(make: String!, model: String): Car @deprecated(reason: "use selectCarById instead")
selectCarById(Id: ID!): Car
}

Command

The following example shows how to deprecate a field in a command:

kind: Command
version: V1
definition:
name: GetEngineSpec
outputType: Engine
graphql:
rootFieldName: getEngineSpec
rootFieldKind: Query
deprecated:
reason: "Fuel Engines are no longer supported from Jan 01 2035"

And the resulting schema:

type Query {
getEngineSpec: Engine @deprecated(reason: "Fuel Engines are no longer supported from Jan 01 2035")
}

ObjectType

The following example shows how to deprecate a field in an ObjectType:

kind: ObjectType
version: V1
definition:
name: Car
fields:
- name: Id
type: String
- name: make
type: String
- name: model
type: String
- name: engine
type: String
deprecated:
reason: Use motor field instead
- name: motor
type: String
graphql:
typeName: Car

And the resulting schema:

type Car {
Id: String
make: String
model: String
engine: String @deprecated(reason: "Use motor field instead")
motor: String
}

Relationship

The following example shows how to deprecate a field in a relationship:

kind: Relationship
version: V1
definition:
name: engineSpec
source: Car
target:
command:
name: GetEngineSpec
mapping:
- source:
fieldPath:
- fieldName: engine
target:
argument:
argumentName: name
deprecated:
reason: Engines on cars are no longer supported from Jan 01 2035

And the resulting schema:

type Car {
Id: String
make: String
model: String
engine: String @deprecated(reason: "Use motor field instead")
motor: String
engineSpec: Engine @deprecated(reason: "Engines on cars are no longer supported from Jan 01 2035")
motorSpec: Motor
}

Default Deprecation Reason

In cases where no deprecation reason is explicitly provided, the @deprecated directive defaults to No longer supported as the reason.

The following example from ObjectType metadata illustrates deprecating a field without specifying a reason.

kind: ObjectType
version: V1
definition:
name: Car
fields:
- name: Id
type: String
- name: make
type: String
- name: model
type: String
- name: engine
type: String
deprecated:
reason: null
- name: motor
type: String
graphql:
typeName: Car

And the resulting schema:

type Car {
Id: String

model: String
engine: String @deprecated(reason: "No longer supported")
motor: String
}
Loading...