{"id":108059,"date":"2023-06-17T06:41:53","date_gmt":"2023-06-17T06:41:53","guid":{"rendered":"https:\/\/showbizztoday.com\/index.php\/2023\/06\/17\/migrating-netflix-to-graphql-safely-by-netflix-technology-blog-jun-2023\/"},"modified":"2023-06-17T06:41:54","modified_gmt":"2023-06-17T06:41:54","slug":"migrating-netflix-to-graphql-safely-by-netflix-technology-blog-jun-2023","status":"publish","type":"post","link":"https:\/\/showbizztoday.com\/index.php\/2023\/06\/17\/migrating-netflix-to-graphql-safely-by-netflix-technology-blog-jun-2023\/","title":{"rendered":"Migrating Netflix to GraphQL Safely | by Netflix Technology Blog | Jun, 2023"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<div class=\"\">\n<div class=\"hr hs ht hu hv\">\n<div class=\"speechify-ignore ab co\">\n<div class=\"speechify-ignore bg l\">\n<div class=\"hw hx hy hz ia ab\">\n<div>\n<div class=\"ab ib\"><a href=\"https:\/\/netflixtechblog.medium.com\/?source=post_page-----8e1e4d4f1e72--------------------------------\" rel=\"noopener follow\" target=\"_blank\"><\/p>\n<div>\n<div class=\"bl\" aria-hidden=\"false\">\n<div class=\"l ic id bx ie if\">\n<div class=\"l ff\"><img decoding=\"async\" alt=\"Netflix Technology Blog\" class=\"l fa bx dc dd cw\" src=\"https:\/\/miro.medium.com\/v2\/resize:fill:88:88\/1*BJWRqfSMf9Da9vsXG9EBRQ.jpeg\" width=\"44\" height=\"44\" loading=\"lazy\"\/><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><\/a><a href=\"https:\/\/netflixtechblog.com\/?source=post_page-----8e1e4d4f1e72--------------------------------\" rel=\"noopener  ugc nofollow\" target=\"_blank\"><\/p>\n<div class=\"ij ab ff\">\n<div>\n<div class=\"bl\" aria-hidden=\"false\">\n<div class=\"l ik il bx ie im\">\n<div class=\"l ff\"><img decoding=\"async\" alt=\"Netflix TechBlog\" class=\"l fa bx bq in cw\" src=\"https:\/\/miro.medium.com\/v2\/resize:fill:48:48\/1*ty4NvNrGg4ReETxqU2N3Og.png\" width=\"24\" height=\"24\" loading=\"lazy\"\/><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><\/a><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p id=\"5868\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">By <a class=\"af nq\" href=\"https:\/\/www.linkedin.com\/in\/jennifer-shin-0019a516\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Jennifer Shin<\/a>, <a class=\"af nq\" href=\"https:\/\/www.linkedin.com\/in\/tejas-shikhare-81027b19\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Tejas Shikhare<\/a>, <a class=\"af nq\" href=\"https:\/\/www.linkedin.com\/in\/willemmanuel\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Will Emmanuel<\/a><\/p>\n<p id=\"00f0\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">In 2022, a serious change was made to Netflix\u2019s iOS and Android purposes. We migrated Netflix\u2019s cell apps to GraphQL with zero downtime, which concerned a complete overhaul from the shopper to the API layer.<\/p>\n<p id=\"f179\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Until just lately, an inside API framework, <a class=\"af nq\" href=\"https:\/\/netflix.github.io\/falcor\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Falcor<\/a>, powered our cell apps. They are actually backed by <a class=\"af nq\" rel=\"noopener ugc nofollow\" target=\"_blank\" href=\"https:\/\/netflixtechblog.com\/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2\">Federated GraphQL<\/a>, a distributed strategy to APIs the place area groups can independently handle and personal particular sections of the API.<\/p>\n<p id=\"663a\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Doing this <strong class=\"mu gr\">safely<\/strong> for 100s of thousands and thousands of shoppers with out disruption is exceptionally difficult, particularly contemplating the numerous dimensions of change concerned. This weblog submit will share broadly-applicable strategies (past GraphQL) we used to carry out this migration. The three methods we are going to focus on immediately are <strong class=\"mu gr\">AB Testing<\/strong>, <strong class=\"mu gr\">Replay Testing,<\/strong> and <strong class=\"mu gr\">Sticky Canaries<\/strong>.<\/p>\n<p id=\"249a\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">Before diving into these strategies, let\u2019s briefly look at the migration plan.<\/p>\n<p id=\"0221\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\"><strong class=\"mu gr\">Before GraphQL: Monolithic Falcor API carried out and maintained by the API Team<\/strong><\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov ow\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*9b08XEVCUiNEG10039-UyQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*9b08XEVCUiNEG10039-UyQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*9b08XEVCUiNEG10039-UyQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*9b08XEVCUiNEG10039-UyQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*9b08XEVCUiNEG10039-UyQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*9b08XEVCUiNEG10039-UyQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*9b08XEVCUiNEG10039-UyQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*9b08XEVCUiNEG10039-UyQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"336\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"dc3e\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Before transferring to GraphQL, our API layer consisted of a monolithic server constructed with <a class=\"af nq\" href=\"https:\/\/netflix.github.io\/falcor\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Falcor<\/a>. A single API staff maintained each the Java implementation of the Falcor framework <em class=\"pj\">and<\/em> the API Server.<\/p>\n<p id=\"7ad5\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\"><strong class=\"mu gr\">Created a GraphQL Shim Service on prime of our current Monolith Falcor API.<\/strong><\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov pk\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*DwoVONp2LLEuJ86UuyiWqQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*DwoVONp2LLEuJ86UuyiWqQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*DwoVONp2LLEuJ86UuyiWqQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*DwoVONp2LLEuJ86UuyiWqQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*DwoVONp2LLEuJ86UuyiWqQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*DwoVONp2LLEuJ86UuyiWqQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*DwoVONp2LLEuJ86UuyiWqQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*DwoVONp2LLEuJ86UuyiWqQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"262\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"8fe5\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">By the summer season of 2020, many UI engineers had been prepared to maneuver to GraphQL. Instead of embarking on a full-fledged migration prime to backside, we created a GraphQL shim on prime of our current Falcor API. The GraphQL shim enabled shopper engineers to maneuver shortly onto GraphQL, determine client-side considerations like cache normalization, experiment with totally different GraphQL shoppers, and examine shopper efficiency with out being blocked by server-side migrations. To launch Phase 1 safely, we used <strong class=\"mu gr\">AB Testing<\/strong>.<\/p>\n<p id=\"fd21\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\"><strong class=\"mu gr\">Deprecate the GraphQL Shim Service and Legacy API Monolith in favor of GraphQL companies owned by the area groups.<\/strong><\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov pl\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*pIaQcrZRPruNX_TzKcdR5Q.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*pIaQcrZRPruNX_TzKcdR5Q.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*pIaQcrZRPruNX_TzKcdR5Q.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*pIaQcrZRPruNX_TzKcdR5Q.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*pIaQcrZRPruNX_TzKcdR5Q.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*pIaQcrZRPruNX_TzKcdR5Q.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*pIaQcrZRPruNX_TzKcdR5Q.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*pIaQcrZRPruNX_TzKcdR5Q.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"362\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"7f89\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We didn\u2019t need the legacy Falcor API to linger without end, so we leaned into Federated GraphQL to energy a single GraphQL API with a number of GraphQL servers.<\/p>\n<p id=\"190d\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We might additionally swap out the implementation of a area from GraphQL Shim to Video API with federation directives. To launch Phase 2 safely, we used <strong class=\"mu gr\">Replay Testing<\/strong> and <strong class=\"mu gr\">Sticky Canaries<\/strong>.<\/p>\n<p id=\"1b3c\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">Two key elements decided our testing methods:<\/p>\n<ul class=\"\">\n<li id=\"f773\" class=\"ms mt gq mu b mv mw mx my mz na nb nc pm ne nf ng pn ni nj nk po nm nn no np pp pq pr bj\">Functional vs. non-functional necessities<\/li>\n<li id=\"b25a\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Idempotency<\/li>\n<\/ul>\n<p id=\"c053\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">If we had been testing <strong class=\"mu gr\">useful necessities<\/strong> like information accuracy, and if the request was <strong class=\"mu gr\">idempotent<\/strong>, we relied on <strong class=\"mu gr\">Replay Testing<\/strong>. We knew we might check the identical question with the identical inputs and constantly count on the identical outcomes.<\/p>\n<p id=\"1f23\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We couldn\u2019t replay check GraphQL queries or mutations that requested non-idempotent fields.<\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div class=\"ou ov px\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1292\/format:webp\/1*6AUD_2oUUTauxY5mo_BM9Q.png 1292w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 646px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*6AUD_2oUUTauxY5mo_BM9Q.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*6AUD_2oUUTauxY5mo_BM9Q.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*6AUD_2oUUTauxY5mo_BM9Q.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*6AUD_2oUUTauxY5mo_BM9Q.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*6AUD_2oUUTauxY5mo_BM9Q.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*6AUD_2oUUTauxY5mo_BM9Q.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1292\/1*6AUD_2oUUTauxY5mo_BM9Q.png 1292w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 646px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"646\" height=\"765\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/figure>\n<p id=\"637b\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">And we positively couldn\u2019t replay check <strong class=\"mu gr\">non-functional necessities<\/strong> like caching and logging consumer interplay. In such circumstances, we weren&#8217;t testing for response information however total habits. So, we relied on higher-level metrics-based testing: <strong class=\"mu gr\">AB Testing <\/strong>and<strong class=\"mu gr\"> Sticky Canaries<\/strong>.<\/p>\n<p id=\"7831\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Let\u2019s focus on the three testing methods in additional element.<\/p>\n<p id=\"4404\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">Netflix historically makes use of AB Testing to guage whether or not new product options resonate with prospects. <strong class=\"mu gr\">In Phase 1,<\/strong> we leveraged the AB testing framework to isolate a consumer section into two teams totaling 1 million customers. The management group\u2019s site visitors utilized the legacy Falcor stack, whereas the experiment inhabitants leveraged the brand new GraphQL shopper and was directed to the GraphQL Shim. To decide buyer impression, we might examine varied metrics similar to error charges, latencies, and time to render.<\/p>\n<p id=\"bb3c\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We arrange a client-side AB experiment that examined Falcor versus GraphQL and reported coarse-grained high quality of expertise metrics (<strong class=\"mu gr\">QoE<\/strong>). The AB experiment outcomes hinted that GraphQL\u2019s correctness was less than par with the legacy system. We spent the following few months diving into these high-level metrics and fixing points similar to cache TTLs, flawed shopper assumptions, and so on.<\/p>\n<h2 id=\"8905\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Wins<\/h2>\n<p id=\"c256\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\"><strong class=\"mu gr\">High-Level Health Metrics: <\/strong>AB Testing supplied the peace of mind we wanted in our total client-side GraphQL implementation. This helped us efficiently migrate 100% of the site visitors on the cell homepage canvas to GraphQL in 6 months.<\/p>\n<h2 id=\"1a7a\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Gotchas<\/h2>\n<p id=\"5d47\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\"><strong class=\"mu gr\">Error Diagnosis: <\/strong>With an AB check, we might see coarse-grained metrics which pointed to potential points, however it was difficult<strong class=\"mu gr\"> to diagnose<\/strong> the precise points.<\/p>\n<p id=\"3374\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">The subsequent section within the migration was to reimplement our current Falcor API in a GraphQL-first server (Video API Service). The Falcor API had turn out to be a logic-heavy monolith with over a decade of tech debt. So we had to make sure that the reimplemented Video API server was bug-free and similar to the already productized Shim service.<\/p>\n<p id=\"38d6\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We developed a Replay Testing device to confirm that <strong class=\"mu gr\">idempotent<\/strong> APIs had been migrated appropriately from the GraphQL Shim to the Video API service.<\/p>\n<p id=\"7ad1\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">The Replay Testing framework leverages the <em class=\"pj\">@override<\/em> directive obtainable in GraphQL Federation. This directive tells the GraphQL Gateway to route to 1 GraphQL server over one other. Take, as an illustration, the next two GraphQL schemas outlined by the Shim Service and the Video Service:<\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov qn\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*C68WgNffpOMi88xWtBjpXQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*C68WgNffpOMi88xWtBjpXQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*C68WgNffpOMi88xWtBjpXQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*C68WgNffpOMi88xWtBjpXQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*C68WgNffpOMi88xWtBjpXQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*C68WgNffpOMi88xWtBjpXQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*C68WgNffpOMi88xWtBjpXQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*C68WgNffpOMi88xWtBjpXQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"151\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"3ecb\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">The GraphQL Shim first outlined the <em class=\"pj\">certificationRating<\/em> area (issues like Rated R or PG-13) in Phase 1. In Phase 2, we stood up the VideoService and outlined the identical <em class=\"pj\">certificationRating<\/em> area marked with the <em class=\"pj\">@override<\/em> directive. The presence of the similar area with the <em class=\"pj\">@override<\/em> directive knowledgeable the GraphQL Gateway to route the decision of this area to the brand new Video Service slightly than the outdated Shim Service.<\/p>\n<p id=\"3453\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">The Replay Tester device samples uncooked site visitors streams from <a class=\"af nq\" href=\"https:\/\/netflix.github.io\/mantis\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Mantis<\/a>. With these sampled occasions, the device can seize a stay request from manufacturing and run an <strong class=\"mu gr\">similar<\/strong> GraphQL question towards each the GraphQL Shim and the brand new Video API service. The device then compares the outcomes and outputs any variations in response payloads.<\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov qo\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*u38PDW5BKHqtOEui3_WQjA.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*u38PDW5BKHqtOEui3_WQjA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*u38PDW5BKHqtOEui3_WQjA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*u38PDW5BKHqtOEui3_WQjA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*u38PDW5BKHqtOEui3_WQjA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*u38PDW5BKHqtOEui3_WQjA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*u38PDW5BKHqtOEui3_WQjA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*u38PDW5BKHqtOEui3_WQjA.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"464\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"6e0c\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\"><strong class=\"mu gr\">Note: We don&#8217;t replay check Personally Identifiable Information. It\u2019s used just for non-sensitive product options on the Netflix UI.<\/strong><\/p>\n<p id=\"80ce\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Once the check is accomplished, the engineer can view the diffs displayed as a <em class=\"pj\">flattened JSON node<\/em>. You can see the management worth on the left facet of the comma in parentheses and the experiment worth on the proper.<\/p>\n<pre class=\"ox oy oz pa pb qp qq qr bo qs qt qu\"><span id=\"fabb\" class=\"qv ns gq qq b bf qw qx l qy qz\">\/information\/movies\/0\/tags\/3\/id: (81496962, null)<\/span><\/pre>\n<pre class=\"ra qp qq qr bo qs qt qu\"><span id=\"c602\" class=\"qv ns gq qq b bf qw qx l qy qz\">\/information\/movies\/0\/tags\/5\/displayName: (S\u00e9rie, worth: \u201cS303251rie\u201d)<\/span><\/pre>\n<p id=\"aeef\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We captured two diffs above, the primary had lacking information for an ID area within the experiment, and the second had an encoding distinction. We additionally noticed variations in localization, date precisions, and floating level accuracy. It gave us confidence in replicated enterprise logic, the place subscriber plans and consumer geographic location decided the shopper\u2019s catalog availability.<\/p>\n<h2 id=\"8afe\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Wins<\/h2>\n<ul class=\"\">\n<li id=\"69cd\" class=\"ms mt gq mu b mv op mx my mz oq nb nc pm or nf ng pn os nj nk po ot nn no np pp pq pr bj\"><strong class=\"mu gr\">Confidence<\/strong> in parity between the 2 GraphQL Implementations<\/li>\n<li id=\"d3be\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Enabled tuning<\/strong> <strong class=\"mu gr\">configs<\/strong> in circumstances the place information was lacking as a consequence of over-eager timeouts<\/li>\n<li id=\"f271\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Tested<\/strong> <strong class=\"mu gr\">enterprise logic<\/strong> that required many (unknown) inputs and the place correctness will be exhausting to eyeball<\/li>\n<\/ul>\n<h2 id=\"8f09\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Gotchas<\/h2>\n<ul class=\"\">\n<li id=\"b889\" class=\"ms mt gq mu b mv op mx my mz oq nb nc pm or nf ng pn os nj nk po ot nn no np pp pq pr bj\"><strong class=\"mu gr\">PII<\/strong> and non-idempotent APIs ought to <strong class=\"mu gr\">not<\/strong> be examined utilizing Replay Tests, and it could be beneficial to have a mechanism to <strong class=\"mu gr\"><em class=\"pj\">forestall<\/em><\/strong> that.<\/li>\n<li id=\"a289\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Manually constructed queries<\/strong> are solely pretty much as good because the options the developer remembers to check. We ended up with untested fields just because we forgot about them.<\/li>\n<li id=\"6d9b\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Correctness:<\/strong> The concept of correctness will be complicated too. For instance, is it extra appropriate for an array to be empty or null, or is it simply noise? Ultimately, we matched the present habits as a lot as attainable as a result of verifying the robustness of the shopper\u2019s error dealing with was troublesome.<\/li>\n<\/ul>\n<p id=\"7ab6\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">Despite these shortcomings, Replay Testing was a key indicator that we had achieved useful correctness of <em class=\"pj\">most<\/em> idempotent queries.<\/p>\n<p id=\"4c39\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">While Replay Testing validates the useful correctness of the brand new GraphQL APIs, it doesn&#8217;t present any efficiency or enterprise metric perception, such because the <strong class=\"mu gr\">total perceived well being of consumer interplay<\/strong>. Are customers clicking play on the similar charges? Are issues loading in time earlier than the consumer loses curiosity? Replay Testing additionally can&#8217;t be used for non-idempotent API validation. We reached for a Netflix device known as the Sticky Canary to construct confidence.<\/p>\n<p id=\"2597\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">A Sticky Canary is an infrastructure experiment the place prospects are assigned both to a canary or baseline host for your complete period of an experiment. All incoming site visitors is allotted to an experimental or baseline host based mostly on their gadget and profile, much like a bucket hash. The experimental host deployment serves all the shoppers assigned to the experiment. Watch our <a class=\"af nq\" href=\"https:\/\/www.youtube.com\/watch?v=Xbn65E-BQhA\" rel=\"noopener ugc nofollow\" target=\"_blank\">Chaos Engineering<\/a> discuss from AWS Reinvent to be taught extra about Sticky Canaries.<\/p>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov rb\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*4jAIZZ4_a7h7NwL8kKiA1A.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"308\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"78f4\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">In the case of our GraphQL APIs, we used a Sticky Canary experiment to<strong class=\"mu gr\"> run two situations of our GraphQL gateway<\/strong>. The <strong class=\"mu gr\">baseline<\/strong> gateway used the present schema, which routes all site visitors to the GraphQL Shim. The <strong class=\"mu gr\">experimental<\/strong> gateway used the brand new proposed schema, which routes site visitors to the newest Video API service. <a class=\"af nq\" href=\"https:\/\/github.com\/Netflix\/zuul\" rel=\"noopener ugc nofollow\" target=\"_blank\">Zuul<\/a>, our major edge gateway, assigns site visitors to both cluster based mostly on the experiment parameters.<\/p>\n<p id=\"4b0b\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We then acquire and analyze the efficiency of the 2 clusters. Some KPIs we monitor intently embody:<\/p>\n<ul class=\"\">\n<li id=\"8a68\" class=\"ms mt gq mu b mv mw mx my mz na nb nc pm ne nf ng pn ni nj nk po nm nn no np pp pq pr bj\">Median and tail latencies<\/li>\n<li id=\"77c9\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Error charges<\/li>\n<li id=\"7d23\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Logs<\/li>\n<li id=\"43cb\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Resource utilization\u2013CPU, community site visitors, reminiscence, disk<\/li>\n<li id=\"f2e9\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Device QoE (Quality of Experience) metrics<\/li>\n<li id=\"8c37\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\">Streaming well being metrics<\/li>\n<\/ul>\n<figure class=\"ox oy oz pa pb pc ou ov paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"pd pe ff pf bg pg\">\n<div class=\"ou ov rc\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*SzHeBP1qU722lruPiOvmJQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\" type=\"image\/webp\"\/><source data-testid=\"og\" srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*SzHeBP1qU722lruPiOvmJQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*SzHeBP1qU722lruPiOvmJQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*SzHeBP1qU722lruPiOvmJQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*SzHeBP1qU722lruPiOvmJQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*SzHeBP1qU722lruPiOvmJQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*SzHeBP1qU722lruPiOvmJQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*SzHeBP1qU722lruPiOvmJQ.png 1400w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px\"\/><img alt=\"\" class=\"bg ph pi c\" width=\"700\" height=\"467\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"2d10\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">We began small, with tiny buyer allocations for hour-long experiments. After validating efficiency, we slowly constructed up scope. We elevated the share of buyer allocations, launched multi-region checks, and finally 12-hour or day-long experiments. Validating alongside the best way is important since Sticky Canaries impression stay manufacturing site visitors and are assigned persistently to a buyer.<\/p>\n<p id=\"f089\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">After a number of sticky canary experiments, we had assurance that section 2 of the migration improved all core metrics, and we might dial up GraphQL globally with confidence.<\/p>\n<h2 id=\"8d41\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Wins<\/h2>\n<p id=\"8d9a\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">Sticky Canaries was important to construct confidence in our new GraphQL companies.<\/p>\n<ul class=\"\">\n<li id=\"9151\" class=\"ms mt gq mu b mv mw mx my mz na nb nc pm ne nf ng pn ni nj nk po nm nn no np pp pq pr bj\"><strong class=\"mu gr\">Non-Idempotent APIs:<\/strong> these checks are appropriate with mutating or non-idempotent APIs<\/li>\n<li id=\"6fc2\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Business metrics:<\/strong> Sticky Canaries validated our core Netflix enterprise metrics had improved after the migration<\/li>\n<li id=\"baad\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">System efficiency:<\/strong> Insights into latency and useful resource utilization assist us perceive how scaling profiles change after migration<\/li>\n<\/ul>\n<h2 id=\"a4d0\" class=\"py ns gq be nt pz qa dx nx qb qc dz ob nd qd qe qf nh qg qh qi nl qj qk ql qm bj\">Gotchas<\/h2>\n<ul class=\"\">\n<li id=\"1eb3\" class=\"ms mt gq mu b mv op mx my mz oq nb nc pm or nf ng pn os nj nk po ot nn no np pp pq pr bj\"><strong class=\"mu gr\">Negative Customer Impact: <\/strong>Sticky Canaries can impression actual customers. We wanted confidence in our new companies earlier than persistently routing some prospects to them. This is partially mitigated by <em class=\"pj\">real-time impression detection<\/em>, which is able to mechanically cancel experiments.<\/li>\n<li id=\"2c89\" class=\"ms mt gq mu b mv ps mx my mz pt nb nc pm pu nf ng pn pv nj nk po pw nn no np pp pq pr bj\"><strong class=\"mu gr\">Short-lived:<\/strong> Sticky Canaries are meant for short-lived experiments. For longer-lived checks, a full-blown AB check needs to be used.<\/li>\n<\/ul>\n<p id=\"feb3\" class=\"pw-post-body-paragraph ms mt gq mu b mv op mx my mz oq nb nc nd or nf ng nh os nj nk nl ot nn no np gj bj\">Technology is consistently altering, and we, as engineers, spend a big a part of our careers performing migrations. The query will not be whether or not we&#8217;re migrating however whether or not we&#8217;re migrating <strong class=\"mu gr\"><em class=\"pj\">safely<\/em><\/strong>, with zero downtime, in a well timed method.<\/p>\n<p id=\"c543\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">At Netflix, we&#8217;ve developed instruments that guarantee confidence in these migrations, focused towards every particular use case being examined. We lined three instruments, <strong class=\"mu gr\">AB testing<\/strong>, <strong class=\"mu gr\">Replay Testing<\/strong>, and <strong class=\"mu gr\">Sticky Canaries<\/strong> that we used for the GraphQL Migration.<\/p>\n<p id=\"03f5\" class=\"pw-post-body-paragraph ms mt gq mu b mv mw mx my mz na nb nc nd ne nf ng nh ni nj nk nl nm nn no np gj bj\">This weblog submit is a part of our Migrating Critical Traffic sequence. Also, try: Migrating Critical Traffic at Scale (<a class=\"af nq\" rel=\"noopener ugc nofollow\" target=\"_blank\" href=\"https:\/\/netflixtechblog.com\/migrating-critical-traffic-at-scale-with-no-downtime-part-1-ba1c7a1c7835\">half 1<\/a>, <a class=\"af nq\" href=\"https:\/\/netflixtechblog.medium.com\/migrating-critical-traffic-at-scale-with-no-downtime-part-2-4b1c8c7155c1\" rel=\"noopener\" target=\"_blank\">half 2<\/a>) and <a class=\"af nq\" rel=\"noopener ugc nofollow\" target=\"_blank\" href=\"https:\/\/netflixtechblog.com\/ensuring-the-successful-launch-of-ads-on-netflix-f99490fdf1ba\">Ensuring the Successful Launch of Ads<\/a>.<\/p>\n<\/div>\n<p>[ad_2]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] By Jennifer Shin, Tejas Shikhare, Will Emmanuel In 2022, a serious change was made to Netflix\u2019s iOS and Android purposes. We migrated Netflix\u2019s cell apps to GraphQL with zero downtime, which concerned a complete overhaul from the shopper to the API layer. Until just lately, an inside API framework, Falcor, powered our cell apps. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":108061,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37],"tags":[],"class_list":{"0":"post-108059","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-netflix"},"_links":{"self":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/posts\/108059","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/comments?post=108059"}],"version-history":[{"count":0,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/posts\/108059\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/media\/108061"}],"wp:attachment":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/media?parent=108059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/categories?post=108059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/tags?post=108059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}