{"id":5,"date":"2018-01-18T21:21:35","date_gmt":"2018-01-18T21:21:35","guid":{"rendered":"http:\/\/blog.adonlon.org\/?p=5"},"modified":"2018-01-29T22:23:15","modified_gmt":"2018-01-29T22:23:15","slug":"api-versioning","status":"publish","type":"post","link":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/","title":{"rendered":"API Versioning"},"content":{"rendered":"<p>One of the most common pieces of over-the-counter advice with assumed universal applicability of Restful APIs is that you should version your APIs. There are differences of opinion over the best <em>approach<\/em> to versioning but it seems that there\u2019s universal acceptance that it\u2019s a GoodThing(\u2122). I\u2019d like to suggest a slightly more nuanced attitude towards API versioning, which is that you should hope you shouldn\u2019t have to version, aim not to version, but not preclude the possibility of versioning at a later date if you have to.<\/p>\n<p>So to get us started let\u2019s review what we mean by API versioning &#8211; it\u2019s a client server thing and it\u2019s about ensuring that the two have a compatible notion of what the API will do \/ should do and what the request \/ response formats must contain. If the client and server communicate via the same API version then they\u2019re compatible, with no guarantees if they\u2019re not communicating with the same version. As I mentioned before there are different approaches to versioning &#8211; some people embed a version number in their URI structure, some people attach a version number to their media type and use content-negotiation to ensure API compatibility. There\u2019s a religious war going on about which is best and, luckily, we don\u2019t have to enter that here because the 20,000ft perspective is the same &#8211; if a client requests a resource using a version that the server doesn\u2019t support or understand then the client receives an error, typically a 4xx series error (because HTTP is the only protocol you can develop Restful APIs in, right\u2026) such as 404 or 406, although other response codes are available.<\/p>\n<p>The value of API versioning is that it may allow the server to implement breaking API changes without breaking existing clients. So, lets say you want to remove a field from a response document, then you can create \u2018v2\u2019 of your API without that field, while still supporting clients on \u2018v1\u2019 who may use that field. An important thing to note is that, unlike many other versioning ideas in software, API versioning is not about identifying every change to an API, only those which could reasonably break a client. If you just need to add a field to an API it would stay at v1, because existing v1 clients shouldn\u2019t be affected by that change. So, not every API change prompts a version number change &#8211; just the breaking ones. And that amounts to either a deletion or repurposing of a field in a response and adding a required field in a request document.<\/p>\n<p>The big difficulty with versioning is the effort associated with maintaining older versions. As the server-side resource model drifts into new territory the difficulty associated with maintaining the older resource model using a shared infrastructure increases. The requirement to maintain the behaviour of the \u2018old\u2019 API is going to put constraints on what you can expect in other parts of your system &#8211; so if v2 and v1 requests end up going into a shared database it may become difficult to modify the underlying table structure to best represent the business domain due to the nature of the v1 API structure. Conversely, it\u2019s also possible that as the internal server-side infrastructure (whether that\u2019s operational or computational) evolves to best serve the current business model so there\u2019ll have to be effort put into the earlier API implementation to make appropriate use of the shared resources. The v1 implementation may have to do more work to enrich incoming data, to handle internal errors, to implement unexpected computational models (such as asynchronous communication) and suchlike.<\/p>\n<p>In short, older API versions are effectively technical debt and, like all technical debt, they need to be paid down. Naturally it\u2019s not as simple as that in practice but the principle stands. The difficulty is exactly the nature of the interaction which an API is designed to solve &#8211; distributed communication. The problem is that the lifecycle of the client and server are necessarily decoupled. That\u2019s a desirable property of a distributed system. And so API versioning is the go-to solution. Nonetheless, you can\u2019t get away from the fact that the versioning solution introduces technical debt which must be payed down.<\/p>\n<p>In a purely distributed environment that\u2019s pretty much the end of the story &#8211; as a server side developer you can only give people a timeline for change, deprecate the old api with a stern warning and \u2018some time\u2019 later stop supporting it and deal with the barrage of clients which are stubbornly using it still. The truth, however, is that most APIs developed are actually internal and have a small number of known clients. The dynamics in this sort of situation are quite different although the underlying motivation is exactly the same &#8211; the desire to move the API forward and to deprecate, and ultimately remove, \u2018undesired\u2019 features. But when you can interact with your clients directly, and their number is relatively small, then you can work with them to move their clients forward to using the new aspects of an API, with the old ones in place, and then you can remove the old aspects of the API &#8211; thus keeping it clean and ensuring that new clients don\u2019t accidentally use \u2018old\u2019 aspects of the API. Large changes should be broken down into smaller individual changes which are not going to cause client breakage. The only breaking change is removing old features that are no longer used. Everything else involves adding new things, although the \u2018new\u2019 may involve resurrecting \u2018old\u2019 things like names but with a new implementation. All without worrying about a version number &#8211; rather the clients and server evolve their API organically and yet still in a decoupled fashion. So you get the benefits of a decoupled development model and the benefits of not maintaining multiple \u2018versions\u2019 of the API.<\/p>\n<p>So, looking back, my overall point is not that API versioning is a BadThing(\u2122). It\u2019s clearly not, and in certain situations it\u2019s absolutely the only way to manage change without introducing breakage. However, API versioning is not the only solution to the problem of managing change in an API and it certainly doesn\u2019t, on its own, deal with the ultimate problem of actually removing ancient features &#8211; which is what actually allows the API to keep changing. Like The Red Queen in Alice\u2019s Adventures Through The Looking Glass, the API must keep moving to remain in the same place, and that means shedding the old as much as gaining the new. And this is the perspective from which we should consider our approach to API versioning &#8211; how can we keep the API relevant, without allowing cruft to accrete. The received wisdom that we should always explicitly version our API is problematic in that it doesn\u2019t begin from this standpoint, it simply suggests an easy to implement but imperfect solution without detailing the corollary idea that a deprecation management strategy is needed to avoid older API versions strangling our capability to move the API forward.<\/p>\n<p>And so my advice is to understand your situation, who your clients are, whether you can communicate with them and whether they\u2019re amenable to working with you to manage change. And then consider whether explicit versioning is really necessary for your situation. It may be, and it my not be. In either case, the important thing to do is to manage the removal of old and crufty features before they become problems. In other words &#8211; manage your technical debt.<\/p>\n<p><a href=\"http:\/\/www.troyhunt.com\/2014\/02\/your-api-versioning-is-wrong-which-is.html\">http:\/\/www.troyhunt.com\/2014\/02\/your-api-versioning-is-wrong-which-is.html<\/a><\/p>\n<p><a href=\"http:\/\/apiux.com\/2013\/05\/14\/api-versioning\/\">http:\/\/apiux.com\/2013\/05\/14\/api-versioning\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the most common pieces of over-the-counter advice with assumed universal applicability of Restful APIs is that you should version your APIs. There are differences of opinion over the best approach to versioning but it seems that there\u2019s universal acceptance that it\u2019s a GoodThing(\u2122). I\u2019d like to suggest a slightly more nuanced attitude towards [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>API Versioning - Pragmatic Software Engineering<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"API Versioning - Pragmatic Software Engineering\" \/>\n<meta property=\"og:description\" content=\"One of the most common pieces of over-the-counter advice with assumed universal applicability of Restful APIs is that you should version your APIs. There are differences of opinion over the best approach to versioning but it seems that there\u2019s universal acceptance that it\u2019s a GoodThing(\u2122). I\u2019d like to suggest a slightly more nuanced attitude towards [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\" \/>\n<meta property=\"og:site_name\" content=\"Pragmatic Software Engineering\" \/>\n<meta property=\"article:published_time\" content=\"2018-01-18T21:21:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-01-29T22:23:15+00:00\" \/>\n<meta name=\"author\" content=\"alastair\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"alastair\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\"},\"author\":{\"name\":\"alastair\",\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1\"},\"headline\":\"API Versioning\",\"datePublished\":\"2018-01-18T21:21:35+00:00\",\"dateModified\":\"2018-01-29T22:23:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\"},\"wordCount\":1289,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1\"},\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\",\"url\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\",\"name\":\"API Versioning - Pragmatic Software Engineering\",\"isPartOf\":{\"@id\":\"https:\/\/blog.adonlon.org\/#website\"},\"datePublished\":\"2018-01-18T21:21:35+00:00\",\"dateModified\":\"2018-01-29T22:23:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.adonlon.org\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"API Versioning\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.adonlon.org\/#website\",\"url\":\"https:\/\/blog.adonlon.org\/\",\"name\":\"Pragmatic Software Engineering\",\"description\":\"Random thoughts and insights on software engineering\",\"publisher\":{\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.adonlon.org\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1\",\"name\":\"alastair\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/cf9abf1220f449fccd0f6795d12b05cb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/cf9abf1220f449fccd0f6795d12b05cb?s=96&d=mm&r=g\",\"caption\":\"alastair\"},\"logo\":{\"@id\":\"https:\/\/blog.adonlon.org\/#\/schema\/person\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"API Versioning - Pragmatic Software Engineering","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/","og_locale":"en_GB","og_type":"article","og_title":"API Versioning - Pragmatic Software Engineering","og_description":"One of the most common pieces of over-the-counter advice with assumed universal applicability of Restful APIs is that you should version your APIs. There are differences of opinion over the best approach to versioning but it seems that there\u2019s universal acceptance that it\u2019s a GoodThing(\u2122). I\u2019d like to suggest a slightly more nuanced attitude towards [&hellip;]","og_url":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/","og_site_name":"Pragmatic Software Engineering","article_published_time":"2018-01-18T21:21:35+00:00","article_modified_time":"2018-01-29T22:23:15+00:00","author":"alastair","twitter_card":"summary_large_image","twitter_misc":{"Written by":"alastair","Estimated reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#article","isPartOf":{"@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/"},"author":{"name":"alastair","@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1"},"headline":"API Versioning","datePublished":"2018-01-18T21:21:35+00:00","dateModified":"2018-01-29T22:23:15+00:00","mainEntityOfPage":{"@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/"},"wordCount":1289,"commentCount":0,"publisher":{"@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1"},"articleSection":["Uncategorized"],"inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/","url":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/","name":"API Versioning - Pragmatic Software Engineering","isPartOf":{"@id":"https:\/\/blog.adonlon.org\/#website"},"datePublished":"2018-01-18T21:21:35+00:00","dateModified":"2018-01-29T22:23:15+00:00","breadcrumb":{"@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.adonlon.org\/index.php\/2018\/01\/18\/api-versioning\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.adonlon.org\/"},{"@type":"ListItem","position":2,"name":"API Versioning"}]},{"@type":"WebSite","@id":"https:\/\/blog.adonlon.org\/#website","url":"https:\/\/blog.adonlon.org\/","name":"Pragmatic Software Engineering","description":"Random thoughts and insights on software engineering","publisher":{"@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.adonlon.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":["Person","Organization"],"@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/4c5a1b2463425db9814bf8540f8954c1","name":"alastair","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/cf9abf1220f449fccd0f6795d12b05cb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/cf9abf1220f449fccd0f6795d12b05cb?s=96&d=mm&r=g","caption":"alastair"},"logo":{"@id":"https:\/\/blog.adonlon.org\/#\/schema\/person\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/posts\/5","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/comments?post=5"}],"version-history":[{"count":0,"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/posts\/5\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/media?parent=5"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/categories?post=5"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.adonlon.org\/index.php\/wp-json\/wp\/v2\/tags?post=5"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}