I think api versioning is particularly most useful when the api is used by mobile applications because as we know updating mobile applications is way more complicated than the click of a refresh button like in webapps, although for webapps there may be caching issues but still they should be easier( I expect) to deal with.
You never version your api. The idea of versioning your api is orthogonal to restful services. I did not come up with that, Roy Fielding the inventor or rest told you all not to do that nonsense. This is what happens when frontend engineers try to do backend development. This skew protection nonsense is a way to complicated restful design and get money from fronend engineer.
Great video. Definitely is something you need to think about. If your app lives behind a login, a technique I've used before is a /revalidate endpoint that checks if a user needs to re-login. When combined with react-query (refetch queries on window focus), you get lots of control.
The expand then contract strategy works well for breaking DB schema changes, and a similar concept can be used for these breaking API changes as well. You basically add whatever you need to your API to satisfy the new requirements, then optionally test it first, then you deploy the changes on the user/frontend side that consumes the updated API, then you wait X amount of time (usually depending on caching strategies and time until you're confident 99% of users are on new version. can optionally roll-back easily now as well, if errors spike with users on the new version), then you deploy the breaking change, which "contracts" the API schema to the final state. The multi-deployment strategy you explained & vercel seems to use is ofc easier to use and probably preferred for most web apps. Just wanted to mention an alternative approach :)
I think we can provide something like a UI version request header and then API will check if this UI version is compatible with this API version and if not response with some header or error code which UI will know that it's now incompatible with API and just refreshes itself automatically. What do you think about this approach?
Yup that would work I think, although the refreshes would destroy the users form and app state which kind of sucks, so again avoiding breaking changes would be best
Sometimes I feel like web is doing too much backward compatibility works unlike native client that just ask user to hard update the native client otherwise they cannot use it. We are being too nice for breaking changes and at the same time we got more complaint from users. The whole backward compatibility thing is what makes web amazing and long live but it also holds the entire web development back.
I mean we could technically do that on web applications, but forcing people to refresh their page is the best user experience . Usually for the best user experience we end up needing to implement very complex logic and systems. It’s a trade off unfortunately. Maybe if your app is small enough, just deploy at midnight when the activity is low and force everyone to log out or refresh when the update goes out
I feel like simply "returning to monkey" and having some automated way to just attach a build ID to all the requests is better. If the backend receives a request that is outdated, force a refresh.
Well forcing a refresh sucks because if a user just entered in a form with 20 fields, all that data might be cleared if you don’t consider finding ways to persist and restore that data
@WebDevCody true. and if you save the frontend state in the uri, then the new frontend would have a new type of skew. I mean, I guess this type of skew is a little better cause the user can see what has changed? idk. I agree with the 20 fields thing, but maybe that is more rare. maybe I'm just coping and I need to git good.
@@st-jn2gk idk in our app at work we have some complex forms with radio buttons, conditionally showing inputs, multi file uploads. If a user spends 5 minutes filling everything out, including uploading files, having that clear would piss many people off on a force refresh 😂
Anytime I have a form that requires a user to enter a lot of information I always save it to local storage then upon a successful submit I clear it out. This also helps for users who step away and close browser. That way its always exactly where they left off.
Why couldn’t the UI just simply watch for a flag that tells the UI it’s on an old version and if it is go ahead and refresh the page? That seems to be a very simple solution to me. Let’s say UI makes request to old API, and the old API would need to have some sort of way of knowing it’s old, and in the response of the old API back to the user, we send a flag back to the UI that says something like “uiVersion: version_number” and if it doesn’t match the UI version then the UI will automatically refresh and retrieve the new assets. Every API could make a chron job every so often that checks for an update in the UI, or you could broadcast it over a simple websocket that connects the API versions together, perhaps an internal router can be checked before the API code and the check can be done there instead of the API. That’s seems easier than immutable deployments, at least it does in my head. IDK, it doesn’t seem that much easier though, I do think Vercels solution is very nice too.
Thats fine solution but sometimes you might not want to force refresh of your client for reasons like user experience. If its mobile app you might not want to force user to download newer version which handles api changes.
The issue boils down to UX. Refreshing the users browser without their consent is a bad ux. The most id do would be show a model saying a new version is available, but give them the option to continue working on whatever they were doing. The continue working part is the best ux but requires making sure you didn’t deploy breaking changes
but it's still a problem and you'd have to apply ways to address it even when using graphql. a breaking api change is a breaking change; rest vs graph vs rpc won't make a difference.
I think api versioning is particularly most useful when the api is used by mobile applications because as we know updating mobile applications is way more complicated than the click of a refresh button like in webapps, although for webapps there may be caching issues but still they should be easier( I expect) to deal with.
this is where ota comes in handy
You never version your api.
The idea of versioning your api is orthogonal to restful services.
I did not come up with that, Roy Fielding the inventor or rest told you all not to do that nonsense.
This is what happens when frontend engineers try to do backend development.
This skew protection nonsense is a way to complicated restful design and get money from fronend engineer.
It’s mandatory
Great video. Definitely is something you need to think about. If your app lives behind a login, a technique I've used before is a /revalidate endpoint that checks if a user needs to re-login. When combined with react-query (refetch queries on window focus), you get lots of control.
Your diagrams are so useful for a visual learner like myself. Thanks Cody!
Glad they help!
Nice explanation, and drawing the diagram made it easier to understand. Thanks so much!!
These videos are so invaluable. Especially when I cant understand some of these articles or concepts myself.
Love these kinds of videos. I can watch them even when I am burned out
The expand then contract strategy works well for breaking DB schema changes, and a similar concept can be used for these breaking API changes as well. You basically add whatever you need to your API to satisfy the new requirements, then optionally test it first, then you deploy the changes on the user/frontend side that consumes the updated API, then you wait X amount of time (usually depending on caching strategies and time until you're confident 99% of users are on new version. can optionally roll-back easily now as well, if errors spike with users on the new version), then you deploy the breaking change, which "contracts" the API schema to the final state. The multi-deployment strategy you explained & vercel seems to use is ofc easier to use and probably preferred for most web apps. Just wanted to mention an alternative approach :)
Love the content Cody, thanks for posting :)
Love it! And love you!
Love you babe!
Great video! good to know this
Hey Cody, could you do a video explaining Ci/Cd and maybe building one with something like github actions
yeah sure if I get time
Great ❤
I think we can provide something like a UI version request header and then API will check if this UI version is compatible with this API version and if not response with some header or error code which UI will know that it's now incompatible with API and just refreshes itself automatically. What do you think about this approach?
Yup that would work I think, although the refreshes would destroy the users form and app state which kind of sucks, so again avoiding breaking changes would be best
what happens when there is a breaking changes in storage/database ? how 2 different version of api work on the data ?
Sometimes I feel like web is doing too much backward compatibility works unlike native client that just ask user to hard update the native client otherwise they cannot use it.
We are being too nice for breaking changes and at the same time we got more complaint from users.
The whole backward compatibility thing is what makes web amazing and long live but it also holds the entire web development back.
I mean we could technically do that on web applications, but forcing people to refresh their page is the best user experience . Usually for the best user experience we end up needing to implement very complex logic and systems. It’s a trade off unfortunately. Maybe if your app is small enough, just deploy at midnight when the activity is low and force everyone to log out or refresh when the update goes out
I feel like simply "returning to monkey" and having some automated way to just attach a build ID to all the requests is better. If the backend receives a request that is outdated, force a refresh.
Well forcing a refresh sucks because if a user just entered in a form with 20 fields, all that data might be cleared if you don’t consider finding ways to persist and restore that data
@WebDevCody true. and if you save the frontend state in the uri, then the new frontend would have a new type of skew. I mean, I guess this type of skew is a little better cause the user can see what has changed? idk. I agree with the 20 fields thing, but maybe that is more rare. maybe I'm just coping and I need to git good.
@@st-jn2gk idk in our app at work we have some complex forms with radio buttons, conditionally showing inputs, multi file uploads. If a user spends 5 minutes filling everything out, including uploading files, having that clear would piss many people off on a force refresh 😂
Anytime I have a form that requires a user to enter a lot of information I always save it to local storage then upon a successful submit I clear it out. This also helps for users who step away and close browser. That way its always exactly where they left off.
@@WebDevCody You could store complex form input in local storage (if its not sensitive information) and only clear it on form submit, no?
Why couldn’t the UI just simply watch for a flag that tells the UI it’s on an old version and if it is go ahead and refresh the page? That seems to be a very simple solution to me. Let’s say UI makes request to old API, and the old API would need to have some sort of way of knowing it’s old, and in the response of the old API back to the user, we send a flag back to the UI that says something like “uiVersion: version_number” and if it doesn’t match the UI version then the UI will automatically refresh and retrieve the new assets. Every API could make a chron job every so often that checks for an update in the UI, or you could broadcast it over a simple websocket that connects the API versions together, perhaps an internal router can be checked before the API code and the check can be done there instead of the API. That’s seems easier than immutable deployments, at least it does in my head. IDK, it doesn’t seem that much easier though, I do think Vercels solution is very nice too.
Thats fine solution but sometimes you might not want to force refresh of your client for reasons like user experience. If its mobile app you might not want to force user to download newer version which handles api changes.
The issue boils down to UX. Refreshing the users browser without their consent is a bad ux. The most id do would be show a model saying a new version is available, but give them the option to continue working on whatever they were doing. The continue working part is the best ux but requires making sure you didn’t deploy breaking changes
What are you studying for know all this things?
These are just things I’ve learned over the years and decide to make a video on it when I find it relevant
graphQl is the easiest way to manage this problem
Could you elaborate? Genuinely curious!
but it's still a problem and you'd have to apply ways to address it even when using graphql. a breaking api change is a breaking change; rest vs graph vs rpc won't make a difference.
@@WebDevCody Yes, I am not disputing that. I am simply stating that graphQl is the easiest way to manage breaking changes.
@@hardcorecode I’ll defer to your experience because I’ve never used it