NOTE: this document is not being worked on at the moment, instead the Nullability WG are currently exploring an alternative solution that addresses many of the same underlying issues in a different way: [Semantic Nullability RFC](SemanticNullability.md).
At a glanceβ
- Identifier: ClientControlledNullability
- Stage: RFC0: Strawman
- Champion: -
- PR: -
- Related:
- #895 (Client Controlled Nullability)
- FragmentModularity (Fragment Modularity)
- wg#1394 (True Nullability Schema)
Timelineβ
- RFC document updated on 2025-02-24 by Martin Bonnin
- RFC document updated on 2023-11-28 by Benjie Gillam
- RFC document updated on 2023-08-03 by Calvin Cestari
- RFC document updated on 2022-05-16 by Alex Reilly
- RFC document created on 2021-11-04 by Alex Reilly
NOTE: this document is not being worked on at the moment, instead the Nullability WG are currently exploring an alternative solution that addresses many of the same underlying issues in a different way: Semantic Nullability RFC.
RFC: Client Controlled Nullability
Proposed by:
- Alex Reilly - Yelp iOS
- Liz Jakubowski - Yelp iOS
- Mark Larah - Yelp Web
- Sanae Rosen - Yelp Android
- Stephen Spalding - Netflix GraphQL Server Infrastructure
- Wei Xue - Yelp iOS
- Young Min Kim - Netflix UI
This RFC proposes syntax that would allow developers to override schema-defined nullability of fields for individual operations.
Definitionsβ
- Required field - A field which is marked with
!.π Problem Statementβ
In our experience, client developers have been frustrated that the vast majority of fields are nullable. Weβve done this in accordance with official best practice, and we largely agree that this is good practice. From the official GraphQL best practice:
This is because there are many things that can go awry in a networked service backed by databases and other services. A database could go down, an asynchronous action could fail, an exception could be thrown. Beyond simply system failures, authorization can often be granular, where individual fields within a request can have different authorization rules.
The problem with the SDL Non-Nullable (
!) is that it eliminates the possibility of partial failure on a given type. This forces schema authors to decide for which fields partial failure is acceptable. A GraphQL schema author may not be in the best position to predict whether partial failure will be acceptable or unacceptable for every canvas that makes use of a field.While the schema can have nullable fields for valid reasons (such as federation), in some cases the client wants to decide if it accepts a
nullvalue for the result to simplify the client-side logic.π§βπ» Proposed Solutionβ
A client-controlled Non-Nullable designator.
π¬ Behaviorβ
Each client-controlled nullability designator overrides the schema-defined nullability of the field it's attached to for the duration of the operation.
!The proposed client-controlled required designator would have identical semantics to the current schema-defined Non-Null.
β Validationβ
If a developer executed an operation with two fields name
foo, one aStringand the other anInt, the operation would be declared invalid by the server. The same is true if one of the fields is designated required but both are otherwise the same type. In this example,nicknamecould be either aStringor aString!which are two different types and therefor can not be merged:fragment conflictingDifferingResponses on Pet {
... on Dog {
nickname
}
... on Cat {
nickname!
}
}βοΈ Proposed syntaxβ
The client can express that a schema field is required by using the
!syntax in the operation definition:query GetBusinessName($id: String!) {
business(id: $id)? {
name!
}
}
!βWe have chosen
!because!is already being used in the GraphQL spec to indicate that a field in the schema is Non-Nullable, so it will feel familiar to GraphQL developers.Use casesβ
Improve the developer experience using GraphQL client code generatorsβ
Handling nullable values on the client is a major source of frustration for developers, especially when using types generated by client code generators in strongly-typed languages. The proposed required designator would allow GraphQL clients to generate types with more precise nullability requirements for a particular feature. For example, using a GraphQL client like Apollo GraphQL on mobile, the following query
query GetBusinessName($id: String!) {
business(id: $id)? {
name!
}
}would be translated to the following type in Swift.
struct GetBusinessNameQuery {
let id: String
struct Data {
let business: Business?
struct Business {
/// Lack of `?` indicates that `name` will never be `null`
let name: String
}
}
}If a null business name is not acceptable for the feature executing this query, this generated type is more ergonomic to use since the developer does not need to unwrap the value each time itβs accessed.
3rd-party GraphQL APIsβ
Marking a field Non-Nullable in schema is not possible in every use case. For example, when a developer is using a 3rd-party API such as Github's GraphQL API they won't be able to alter Github's schema, but they may still want to have certain fields be required in their application. Even within an organization, ownership rules may dictate that an developer is not allowed to alter a schema they utilize.
β RFC Goalsβ
- Non-nullable syntax that is based off of syntax that developers will already be familiar with
- Enable GraphQL client code generation tools to generate more ergonomic types
π« RFC Non-goals