11/12/2019
collective intelligence driven civic start-up that develops participatory applications.
An API is a contract with our users!
For this, our technical team needs:
Bring new features and improvements
Do not change :
The body of the responses
Query parameters
Available features
Do not break existing user integrations
For users, every upgrade is a major upgrade. 🚧
Problem: You can not make any significant changes after publication. 😱
We must therefore claim to have a perfect API for each version, which is hard ...
We modify our API gradually, adding new features and deprecating usages.
It's much closer to our development model ... We do not rethink our model every year, it evolves little by little.
Facebook's GraphQL schema (over 4 years old, 1,000s of types at this point, and under active change by 100s of engineers) has never needed a versioned breaking change, and still supports 4-year old shipped versions of iOS and Android apps (which unfortunately are still being used).
Ok, but it's an internal GraphQL API ...
We'll announce upcoming breaking changes at least three months before making changes to the GraphQL schema, to give integrators time to make the necessary adjustments. Changes go into effect on the first day of a quarter (January 1st, April 1st, July 1st, or October 1st). For example, if we announce a change on January 15th, it will be made on July 1st.
A good compromise for a public API.
Changelog ~ Twitter ~ RSS
Field `votesCount` will be removed. Use `votes.totalCount` instead. In preparation for an upcoming change to the way we expose counters, this field will only be available inside a connection. Removal on 2019-01-01 UTC.
Include useful information ... Why? How to replace? When?
Take care of the depreciation messages:
Encourage your users to use the new features, it is giving them an interest to no longer use depreciated parts!
We will see together several means of prevention ...
But not a miracle method (sorry)!
Adding new fields and types will not impact existing queries ✌️
With a REST (classic) approach we increase the payload of all customers 😞
Adding a new field is the easiest way to avoid a BC.
Sometimes being specific can save us later. (ex: AddVoteContributionEvent vs VoteEvent)
🤔 Just deprecating for a name is a blocking change that does not give value to customers, avoid it at all costs.
There are only two hard things in Computer Science: cache invalidation and naming things.
Phil Karlton
Tip: Limit the scalars to the strict minimum.
type Event {
name: String
startTime: Date
endTime: Date
}
type TimeRange {
start: Date
end: Date
}
type Event {
name: String
time: TimeRange
}
Is a scalar field enough, a field type would not be better?
The main business object types must always implement Node.
Always check if the list type fields should be paginated or not. If yes, make a Connection.
Each mutation must have its own type Input and Payload.
It is designed for evolutions:
Using nullable is a way to have a stronger schema!
Don't do it : it's annoying for the customer who has to check "null" everywhere and your schema loses its meaning.
If everything is non-nullable the slightest error generates a snowball effect ...
Get inspiration from existing public API.
(and even their mistakes!)
✅ We make sure that the schema is up to date with each commit.
Expliquer le problème
✌️ No risk to merge a Breaking Change!
Move a type or field from the Internal schema to the Public
It's normal not to be sure.
Let's be transparent.
Trust in the design of its API takes time.
We can allow ourselves small mistakes. 😉
Public
Internal
Preview
The use of the Preview schema makes it possible to provide functionalities without being constrained by the BCs policy.
Obviously the goal is that everything that goes through Preview arrives as is in Public.
Who still uses the depreciated field?
How often has the field been used lately?
Query
Analytics
query {
consultations {
title
}
}
No magic but a little analysis... 😉
Type: Query
Field: consultations
Client: 1234
Type: Consultation
Field: title
Client: 1234
This is the key to trusting in the continuous evolution of your API!
GraphQL allows it because it is the client who describes the needs.
Example of what was developed at GitHub.
How often has the field been used lately?
Hey [my-api-client] we notice that you are using our deprecated field `votesCount` on type `Consultation`. This field will be removed in 2 weeks, please use `votes.totalCount` instead !
🚀 Generating a custom message
Who still uses the depreciated field?