{"id":133464,"date":"2024-09-30T11:51:25","date_gmt":"2024-09-30T11:51:25","guid":{"rendered":"https:\/\/showbizztoday.com\/index.php\/2024\/09\/30\/introducing-netflixs-key-value-data-abstraction-layer-by-netflix-technology-blog-sep-2024\/"},"modified":"2024-09-30T11:51:25","modified_gmt":"2024-09-30T11:51:25","slug":"introducing-netflixs-key-value-data-abstraction-layer-by-netflix-technology-blog-sep-2024","status":"publish","type":"post","link":"https:\/\/showbizztoday.com\/index.php\/2024\/09\/30\/introducing-netflixs-key-value-data-abstraction-layer-by-netflix-technology-blog-sep-2024\/","title":{"rendered":"Introducing Netflix\u2019s Key-Value Data Abstraction Layer | by Netflix Technology Blog | Sep, 2024"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<div>\n<div>\n<div class=\"speechify-ignore ab cp\">\n<div class=\"speechify-ignore bh l\">\n<div class=\"hv hw hx hy hz ab\">\n<div>\n<div class=\"ab ia\"><a href=\"https:\/\/netflixtechblog.medium.com\/?source=post_page-----1ea8a0a11b30--------------------------------\" rel=\"noopener follow\" target=\"_blank\"><\/p>\n<div>\n<div class=\"bm\" aria-hidden=\"false\">\n<div class=\"l ib ic by id ie\">\n<div class=\"l fj\"><img decoding=\"async\" alt=\"Netflix Technology Blog\" class=\"l fd by dd de cx\" src=\"https:\/\/miro.medium.com\/v2\/resize:fill:88:88\/1*BJWRqfSMf9Da9vsXG9EBRQ.jpeg\" width=\"44\" height=\"44\" loading=\"lazy\" data-testid=\"authorPhoto\"\/><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><\/a><a href=\"https:\/\/netflixtechblog.com\/?source=post_page-----1ea8a0a11b30--------------------------------\" rel=\"noopener  ugc nofollow\" target=\"_blank\"><\/p>\n<div class=\"ih ab fj\">\n<div>\n<div class=\"bm\" aria-hidden=\"false\">\n<div class=\"l ii ij by id ik\">\n<div class=\"l fj\"><img decoding=\"async\" alt=\"Netflix TechBlog\" class=\"l fd by br il cx\" src=\"https:\/\/miro.medium.com\/v2\/resize:fill:48:48\/1*ty4NvNrGg4ReETxqU2N3Og.png\" width=\"24\" height=\"24\" loading=\"lazy\" data-testid=\"publicationPhoto\"\/><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p><\/a><\/div>\n<\/div>\n<div class=\"bn bh l\">\n<div class=\"l ix\"><span class=\"bf b bg z du\"><\/p>\n<div class=\"ab cn iy iz ja\"><span class=\"bf b bg z du\"><\/p>\n<div class=\"ab ae\"><span data-testid=\"storyReadTime\">13 min learn<\/span><\/p>\n<p><span class=\"l\" aria-hidden=\"true\"><span class=\"bf b bg z du\">\u00b7<\/span><\/span><\/p>\n<p><span data-testid=\"storyPublishDate\">Sep 18, 2024<\/span><\/div>\n<p><\/span><\/div>\n<p><\/span><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p id=\"3a78\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\"><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/vidhya-arvind-11908723\" rel=\"noopener ugc nofollow\" target=\"_blank\">Vidhya Arvind<\/a>, <a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/rummadis\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Rajasekhar Ummadisetty<\/a>, <a class=\"af nv\" href=\"https:\/\/jolynch.github.io\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Joey Lynch<\/a>, <a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/vinaychella\" rel=\"noopener ugc nofollow\" target=\"_blank\">Vinay Chella<\/a><\/p>\n<p id=\"8fe5\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">At Netflix our skill to ship seamless, high-quality, streaming experiences to thousands and thousands of customers hinges on strong, <em class=\"oz\">international<\/em> backend infrastructure. Central to this infrastructure is our use of a number of on-line distributed databases similar to <a class=\"af nv\" href=\"https:\/\/cassandra.apache.org\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">Apache Cassandra<\/a>, a NoSQL database identified for its excessive availability and scalability. Cassandra serves because the spine for a various array of use circumstances inside Netflix, starting from consumer sign-ups and storing viewing histories to supporting real-time analytics and stay streaming.<\/p>\n<p id=\"255e\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">Over time as new key-value databases have been launched and repair homeowners launched new use circumstances, we encountered quite a few challenges with datastore misuse. Firstly, builders struggled to motive about consistency, sturdiness and efficiency on this complicated international deployment throughout a number of shops. Second, builders needed to continuously re-learn new knowledge modeling practices and customary but crucial knowledge entry patterns. These embrace challenges with tail latency and idempotency, managing \u201cwide\u201d partitions with many rows, dealing with single massive \u201cfat\u201d columns, and sluggish response pagination. Additionally, the tight coupling with a number of native database APIs \u2014 APIs that frequently evolve and generally introduce backward-incompatible adjustments \u2014 resulted in org-wide engineering efforts to keep up and optimize our microservice\u2019s knowledge entry.<\/p>\n<p id=\"e872\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">To overcome these challenges, we developed a holistic method that builds upon our <a class=\"af nv\" href=\"https:\/\/netflixtechblog.medium.com\/data-gateway-a-platform-for-growing-and-protecting-the-data-tier-f1ed8db8f5c6\" rel=\"noopener\" target=\"_blank\">Data Gateway Platform<\/a>. This method led to the creation of a number of foundational abstraction companies, probably the most mature of which is our Key-Value (KV) Data Abstraction Layer (DAL). This abstraction simplifies knowledge entry, enhances the reliability of our infrastructure, and allows us to help the broad spectrum of use circumstances that Netflix calls for with minimal developer effort.<\/p>\n<p id=\"92d2\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">In this publish, we dive deep into how Netflix\u2019s KV abstraction works, the architectural rules guiding its design, the challenges we confronted in scaling numerous use circumstances, and the technical improvements which have allowed us to attain the efficiency and reliability required by Netflix\u2019s international operations.<\/p>\n<p id=\"4bde\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The KV knowledge abstraction service was launched to unravel the persistent challenges we confronted with knowledge entry patterns in our distributed databases. Our purpose was to construct a flexible and environment friendly knowledge storage resolution that might deal with all kinds of use circumstances, starting from the best hashmaps to extra complicated knowledge constructions, all whereas guaranteeing excessive availability, tunable consistency, and low latency.<\/p>\n<h2 id=\"653a\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Data Model<\/h2>\n<p id=\"adb9\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">At its core, the KV abstraction is constructed round a <strong class=\"mz gv\"><em class=\"oz\">two-level map<\/em> <\/strong>structure. The first stage is a hashed string <strong class=\"mz gv\">ID<\/strong> (the first key), and the second stage is a <strong class=\"mz gv\"><em class=\"oz\">sorted map of a key-value pair of bytes<\/em><\/strong>. This mannequin helps each easy and complicated knowledge fashions, balancing flexibility and effectivity.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"e089\" class=\"py nx gu pv b bg pz qa l qb qc\">HashMap&lt;String, SortedMap&lt;Bytes, Bytes&gt;&gt;<\/span><\/pre>\n<p id=\"9c5f\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">For complicated knowledge fashions similar to structured <code class=\"cx qd qe qf pv b\">Records<\/code> or time-ordered <code class=\"cx qd qe qf pv b\">Events<\/code>, this two-level method handles hierarchical constructions successfully, permitting associated knowledge to be retrieved collectively. For less complicated use circumstances, it additionally represents flat key-value <code class=\"cx qd qe qf pv b\">Maps<\/code> (e.g. <code class=\"cx qd qe qf pv b\">id \u2192 {\"\" \u2192 worth}<\/code>) or named <code class=\"cx qd qe qf pv b\">Sets<\/code> (e.g.<code class=\"cx qd qe qf pv b\">id \u2192 {key \u2192 \"\"}<\/code>). This adaptability permits the KV abstraction for use in tons of of numerous use circumstances, making it a flexible resolution for managing each easy and complicated knowledge fashions in large-scale infrastructures like Netflix.<\/p>\n<p id=\"e359\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">The KV knowledge might be visualized at a excessive stage, as proven within the diagram under, the place three data are proven.<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh qi\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*9Ny8Uc-diSDnVGnk 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*9Ny8Uc-diSDnVGnk 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*9Ny8Uc-diSDnVGnk 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*9Ny8Uc-diSDnVGnk 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*9Ny8Uc-diSDnVGnk 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*9Ny8Uc-diSDnVGnk 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*9Ny8Uc-diSDnVGnk 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\/0*9Ny8Uc-diSDnVGnk 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*9Ny8Uc-diSDnVGnk 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*9Ny8Uc-diSDnVGnk 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*9Ny8Uc-diSDnVGnk 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*9Ny8Uc-diSDnVGnk 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*9Ny8Uc-diSDnVGnk 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/0*9Ny8Uc-diSDnVGnk 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=\"bh me qo c\" width=\"700\" height=\"442\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"1668\" class=\"py nx gu pv b bg pz qa l qb qc\">message Item (   <br\/>Bytes    key,<br\/>Bytes    worth,<br\/>Metadata metadata,<br\/>Integer  chunk<br\/>)<\/span><\/pre>\n<h2 id=\"9585\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Database Agnostic Abstraction<\/h2>\n<p id=\"7654\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The KV abstraction is designed to cover the implementation particulars of the underlying database, providing a constant interface to utility builders whatever the optimum storage system for that use case. While Cassandra is one instance, the abstraction works with a number of knowledge shops like <a class=\"af nv\" href=\"https:\/\/github.com\/Netflix\/EVCache\" rel=\"noopener ugc nofollow\" target=\"_blank\">EVCache<\/a>, <a class=\"af nv\" href=\"https:\/\/aws.amazon.com\/dynamodb\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">DynamoDB<\/a>, <a class=\"af nv\" href=\"https:\/\/rocksdb.org\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">RocksDB<\/a>, and many others\u2026<\/p>\n<p id=\"6b60\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">For instance, when applied with Cassandra, the abstraction leverages Cassandra\u2019s partitioning and clustering capabilities. The file <strong class=\"mz gv\"><em class=\"oz\">ID<\/em><\/strong> acts because the partition key, and the merchandise <strong class=\"mz gv\"><em class=\"oz\">key<\/em><\/strong> because the clustering column:<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh qp\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/1*tMhXVTWqtHt24l1oflpAJQ.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*tMhXVTWqtHt24l1oflpAJQ.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*tMhXVTWqtHt24l1oflpAJQ.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*tMhXVTWqtHt24l1oflpAJQ.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*tMhXVTWqtHt24l1oflpAJQ.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*tMhXVTWqtHt24l1oflpAJQ.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*tMhXVTWqtHt24l1oflpAJQ.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*tMhXVTWqtHt24l1oflpAJQ.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=\"bh me qo c\" width=\"700\" height=\"194\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"17d6\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">The corresponding Data Definition Language (DDL) for this construction in Cassandra is:<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"e122\" class=\"py nx gu pv b bg pz qa l qb qc\">CREATE TABLE IF NOT EXISTS &lt;ns&gt;.&lt;desk&gt; (<br\/>id             textual content,<br\/>key            blob,<br\/>worth          blob,<br\/>value_metadata blob,<p>PRIMARY KEY (id, key))<br\/>WITH CLUSTERING ORDER BY (key &lt;ASC|DESC&gt;)<\/p><\/span><\/pre>\n<h2 id=\"dd6f\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Namespace: Logical and Physical Configuration<\/h2>\n<p id=\"6e76\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">A <strong class=\"mz gv\">namespace<\/strong> defines the place and the way knowledge is saved, offering logical and bodily separation whereas abstracting the underlying storage programs. It additionally serves as central configuration of entry patterns similar to consistency or latency targets. Each namespace might use totally different backends: Cassandra, EVCache, or combos of a number of. This flexibility permits our Data Platform to route totally different use circumstances to probably the most appropriate storage system based mostly on efficiency, sturdiness, and consistency wants. Developers simply present their knowledge drawback reasonably than a database resolution!<\/p>\n<p id=\"898b\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">In this instance configuration, the <code class=\"cx qd qe qf pv b\">ngsegment<\/code> namespace is backed by each a Cassandra cluster and an EVCache caching layer, permitting for extremely sturdy persistent storage <em class=\"oz\">and<\/em> lower-latency level reads.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"294b\" class=\"py nx gu pv b bg pz qa l qb qc\">\"persistence_configuration\":[                                                   <br\/>{                                                                           <br\/>\"id\":\"PRIMARY_STORAGE\",                                                 <br\/>\"physical_storage\": {                                                    <br\/>\"type\":\"CASSANDRA\",                                                 <br\/>\"cluster\":\"cassandra_kv_ngsegment\",                                <br\/>\"dataset\":\"ngsegment\",                                             <br\/>\"table\":\"ngsegment\",                                               <br\/>\"regions\": [\"us-east-1\"],<br\/>\"config\": {<br\/>\"consistency_scope\": \"LOCAL\",<br\/>\"consistency_target\": \"READ_YOUR_WRITES\"<br\/>}                                            <br\/>}                                                                       <br\/>},                                                                          <br\/>{                                                                           <br\/>\"id\":\"CACHE\",                                                           <br\/>\"physical_storage\": {                                                    <br\/>\"sort\":\"CACHE\",                                                     <br\/>\"cluster\":\"evcache_kv_ngsegment\"                                   <br\/>},                                                                      <br\/>\"config\": {                                                              <br\/>\"default_cache_ttl\": 180s                                             <br\/>}                                                                       <br\/>}                                                                           <br\/>] <br\/><\/span><\/pre>\n<p id=\"0ffe\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">To help numerous use-cases, the KV abstraction supplies 4 primary CRUD APIs:<\/p>\n<h2 id=\"b9f2\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">PutItems <strong class=\"al\">\u2014 Write a number of Items to a Record<\/strong><\/h2>\n<p id=\"4d14\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The <code class=\"cx qd qe qf pv b\">PutItems<\/code> API is an upsert operation, it could insert new knowledge or replace present knowledge within the two-level map construction.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"2ca6\" class=\"py nx gu pv b bg pz qa l qb qc\">message PutItemRequest (<br\/>IdempotencyToken idempotency_token,<br\/>string           namespace, <br\/>string           id, <br\/>List&lt;Item&gt;       objects<br\/>)<\/span><\/pre>\n<p id=\"d3db\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">As you possibly can see, the request contains the namespace, Record ID, a number of objects, and an <strong class=\"mz gv\">idempotency token<\/strong> to make sure retries of the identical write are secure. Chunked knowledge might be written by staging chunks after which committing them with acceptable metadata (e.g. variety of chunks).<\/p>\n<h2 id=\"d04a\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">GetItems <strong class=\"al\">\u2014 Read a number of Items from a Record<\/strong><\/h2>\n<p id=\"487c\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The <code class=\"cx qd qe qf pv b\">GetItems<\/code>API supplies a structured and adaptive strategy to fetch knowledge utilizing ID, predicates, and choice mechanisms. This method balances the necessity to retrieve massive volumes of knowledge whereas assembly stringent Service Level Objectives (SLOs) for efficiency and reliability.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"a4b2\" class=\"py nx gu pv b bg pz qa l qb qc\">message GetItemsRequest (<br\/>String              namespace,<br\/>String              id,<br\/>Predicate           predicate,<br\/>Selection           choice,<br\/>Map&lt;String, Struct&gt; indicators<br\/>)<\/span><\/pre>\n<p id=\"ed18\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">The <code class=\"cx qd qe qf pv b\">GetItemsRequest<\/code> contains a number of key parameters:<\/p>\n<ul class=\"\">\n<li id=\"f54d\" class=\"mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Namespace<\/strong>: Specifies the logical dataset or desk<\/li>\n<li id=\"a823\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Id<\/strong>: Identifies the entry within the top-level HashMap<\/li>\n<li id=\"b7f8\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Predicate<\/strong>: Filters the matching objects and might retrieve all objects (<code class=\"cx qd qe qf pv b\">match_all<\/code>), particular objects (<code class=\"cx qd qe qf pv b\">match_keys<\/code>), or a spread (<code class=\"cx qd qe qf pv b\">match_range<\/code>)<\/li>\n<li id=\"a2e5\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Selection<\/strong>: Narrows returned responses for instance <code class=\"cx qd qe qf pv b\">page_size_bytes<\/code> for pagination, <code class=\"cx qd qe qf pv b\">item_limit<\/code> for limiting the full variety of objects throughout pages and <code class=\"cx qd qe qf pv b\">embrace<\/code>\/<code class=\"cx qd qe qf pv b\">exclude<\/code> to incorporate or exclude massive values from responses<\/li>\n<li id=\"9b65\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Signals:<\/strong> Provides in-band signaling to point consumer capabilities, similar to supporting consumer compression or chunking.<\/li>\n<\/ul>\n<p id=\"697f\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">The <code class=\"cx qd qe qf pv b\">GetItemResponse<\/code> message comprises the matching knowledge:<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"f20b\" class=\"py nx gu pv b bg pz qa l qb qc\">message GetItemResponse (<br\/>List&lt;Item&gt;       objects,<br\/>Optional&lt;String&gt; next_page_token<br\/>)<\/span><\/pre>\n<ul class=\"\">\n<li id=\"9d6e\" class=\"mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Items<\/strong>: A listing of retrieved objects based mostly on the <code class=\"cx qd qe qf pv b\">Predicate<\/code> and <code class=\"cx qd qe qf pv b\">Selection<\/code> outlined within the request.<\/li>\n<li id=\"5617\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Next Page Token<\/strong>: An non-obligatory token indicating the place for subsequent reads if wanted, important for dealing with massive knowledge units throughout a number of requests. Pagination is a crucial part for effectively managing knowledge retrieval, particularly when coping with massive datasets that might exceed typical response measurement limits.<\/li>\n<\/ul>\n<h2 id=\"a3d0\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\"><strong class=\"al\">DeleteItems \u2014 Delete a number of Items from a Record<\/strong><\/h2>\n<p id=\"b258\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The <code class=\"cx qd qe qf pv b\">DeleteItems<\/code> API supplies versatile choices for eradicating knowledge, together with record-level, item-level, and vary deletes \u2014 all whereas supporting idempotency.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"329d\" class=\"py nx gu pv b bg pz qa l qb qc\">message DeleteItemsRequest (<br\/>IdempotencyToken idempotency_token,<br\/>String           namespace,<br\/>String           id,<br\/>Predicate        predicate<br\/>)<br\/><\/span><\/pre>\n<p id=\"b5bd\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">Just like within the <code class=\"cx qd qe qf pv b\">GetItems<\/code> API, the <code class=\"cx qd qe qf pv b\">Predicate<\/code> permits a number of Items to be addressed directly:<\/p>\n<ul class=\"\">\n<li id=\"4e42\" class=\"mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Record-Level Deletes (match_all)<\/strong>: Removes all the file in fixed latency whatever the variety of objects within the file.<\/li>\n<li id=\"0b32\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Item-Range Deletes (match_range)<\/strong>: This deletes a spread of things inside a Record. Useful for holding \u201cn-newest\u201d or prefix path deletion.<\/li>\n<li id=\"7525\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Item-Level Deletes (match_keys)<\/strong>: Deletes a number of particular person objects.<\/li>\n<\/ul>\n<p id=\"4f76\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">Some storage engines (any retailer which defers true deletion) similar to Cassandra wrestle with excessive volumes of deletes on account of tombstone and compaction overhead. Key-Value optimizes each file and vary deletes to generate a single tombstone for the operation \u2014 you possibly can be taught extra about tombstones in <a class=\"af nv\" href=\"https:\/\/thelastpickle.com\/blog\/2016\/07\/27\/about-deletes-and-tombstones.html\" rel=\"noopener ugc nofollow\" target=\"_blank\">About Deletes and Tombstones<\/a>.<\/p>\n<p id=\"3569\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">Item-level deletes create many tombstones however KV hides that storage engine complexity through <strong class=\"mz gv\">TTL-based deletes with jitter<\/strong>. Instead of speedy deletion, merchandise metadata is up to date as expired with randomly jittered TTL utilized to stagger deletions. This approach maintains learn pagination protections. While this doesn\u2019t utterly remedy the issue it reduces load spikes and helps preserve constant efficiency whereas compaction catches up. These methods assist preserve system efficiency, cut back learn overhead, and meet SLOs by minimizing the influence of deletes.<\/p>\n<h2 id=\"9f4f\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Complex Mutate and Scan APIs<\/h2>\n<p id=\"d6e0\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">Beyond easy CRUD on single Records, KV additionally helps complicated multi-item and multi-record mutations and scans through <code class=\"cx qd qe qf pv b\">MutateItems<\/code> and <code class=\"cx qd qe qf pv b\">ScanItems<\/code> APIs. <code class=\"cx qd qe qf pv b\">PutItems<\/code> additionally helps atomic writes of enormous blob knowledge inside a single <code class=\"cx qd qe qf pv b\">Item<\/code> through a chunked protocol. These complicated APIs require cautious consideration to make sure predictable linear low-latency and we are going to share particulars on their implementation in a future publish.<\/p>\n<h2 id=\"c223\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Idempotency to battle tail latencies<\/h2>\n<p id=\"d7cd\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">To guarantee knowledge integrity the <code class=\"cx qd qe qf pv b\">PutItems<\/code> and <code class=\"cx qd qe qf pv b\">DeleteItems<\/code> APIs use <strong class=\"mz gv\">idempotency tokens<\/strong>, which uniquely establish every mutative operation and assure that operations are logically executed so as, even when hedged or retried for latency causes. This is particularly essential in last-write-wins databases like Cassandra, the place guaranteeing the right order and de-duplication of requests is significant.<\/p>\n<p id=\"b8d5\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">In the Key-Value abstraction, idempotency tokens comprise a era timestamp and random nonce token. Either or each could also be required by backing storage engines to de-duplicate mutations.<\/p>\n<pre class=\"pp pq pr ps pt pu pv pw bp px bb bk\"><span id=\"8899\" class=\"py nx gu pv b bg pz qa l qb qc\">message IdempotencyToken (<br\/>Timestamp generation_time,<br\/>String    token<br\/>)<\/span><\/pre>\n<p id=\"3089\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">At Netflix, <strong class=\"mz gv\">client-generated monotonic tokens<\/strong> are most well-liked on account of their reliability, particularly in environments the place community delays may influence server-side token era. This combines a consumer supplied monotonic <code class=\"cx qd qe qf pv b\">generation_time<\/code> timestamp with a 128 bit random UUID <code class=\"cx qd qe qf pv b\">token<\/code>. Although clock-based token era can endure from clock skew, our exams on EC2 Nitro cases present drift is minimal (beneath 1 millisecond). In some circumstances that require stronger ordering, regionally distinctive tokens might be generated utilizing instruments like Zookeeper, or globally distinctive tokens similar to a transaction IDs can be utilized.<\/p>\n<p id=\"abaa\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">The following graphs illustrate the noticed <a class=\"af nv\" href=\"https:\/\/docs.google.com\/document\/d\/1XLBjQ9scZCy-xIo51Rs--CSdFV781fnp5hXdXTBAk1k\/edit\" rel=\"noopener ugc nofollow\" target=\"_blank\">clock skew<\/a> on our Cassandra fleet, suggesting the security of this method on trendy cloud VMs with direct entry to high-quality clocks. To additional preserve security, KV servers reject writes bearing tokens with massive drift each stopping silent write discard (write has timestamp far in previous) and immutable doomstones (write has a timestamp far in future) in storage engines susceptible to these.<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh qy\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*gTmQpPIyZcKDb4Fb 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*gTmQpPIyZcKDb4Fb 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*gTmQpPIyZcKDb4Fb 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*gTmQpPIyZcKDb4Fb 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*gTmQpPIyZcKDb4Fb 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*gTmQpPIyZcKDb4Fb 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*gTmQpPIyZcKDb4Fb 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\/0*gTmQpPIyZcKDb4Fb 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*gTmQpPIyZcKDb4Fb 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*gTmQpPIyZcKDb4Fb 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*gTmQpPIyZcKDb4Fb 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*gTmQpPIyZcKDb4Fb 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*gTmQpPIyZcKDb4Fb 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/0*gTmQpPIyZcKDb4Fb 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=\"bh me qo c\" width=\"700\" height=\"685\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<h2 id=\"7b42\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Handling Large Data via Chunking<\/h2>\n<p id=\"4ff0\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">Key-Value can be designed to effectively deal with massive blobs, a standard problem for conventional key-value shops. Databases typically face limitations on the quantity of knowledge that may be saved per key or partition. To tackle these constraints, KV makes use of clear <strong class=\"mz gv\">chunking<\/strong> to handle massive knowledge effectively.<\/p>\n<p id=\"2392\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">For objects smaller than 1 MiB, knowledge is saved instantly in the primary backing storage (e.g. Cassandra), guaranteeing quick and environment friendly entry. However, for bigger objects, solely the <strong class=\"mz gv\">id<\/strong>, <strong class=\"mz gv\">key<\/strong>, and <strong class=\"mz gv\">metadata<\/strong> are saved within the main storage, whereas the precise knowledge is cut up into smaller chunks and saved individually in chunk storage. This chunk storage may also be Cassandra however with a unique partitioning scheme optimized for dealing with massive values. The idempotency token ties all these writes collectively into one atomic operation.<\/p>\n<p id=\"605e\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">By splitting massive objects into chunks, we make sure that latency scales linearly with the dimensions of the info, making the system each predictable and environment friendly. A future weblog publish will describe the <strong class=\"mz gv\">chunking structure<\/strong> in additional element, together with its intricacies and optimization methods.<\/p>\n<h2 id=\"2b4f\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Client-Side Compression<\/h2>\n<p id=\"5ad2\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The KV abstraction leverages client-side payload compression to optimize efficiency, particularly for big knowledge transfers. While many databases provide server-side compression, dealing with compression on the consumer aspect reduces costly server CPU utilization, community bandwidth, and disk I\/O. In one among our deployments, which helps energy Netflix\u2019s search, enabling client-side compression lowered payload sizes by 75%, considerably bettering price effectivity.<\/p>\n<h2 id=\"5805\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Smarter Pagination<\/h2>\n<p id=\"739c\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">We selected payload measurement in bytes because the restrict per response web page reasonably than the variety of objects as a result of it permits us to supply predictable operation SLOs. For occasion, we are able to present a single-digit millisecond SLO on a 2 MiB web page learn. Conversely, utilizing the variety of objects per web page because the restrict would end in unpredictable latencies on account of vital variations in merchandise measurement. A request for 10 objects per web page may end in vastly totally different latencies if every merchandise was 1 KiB versus 1 MiB.<\/p>\n<p id=\"21ce\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">Using bytes as a restrict poses challenges as few backing shops help byte-based pagination; most knowledge shops use the variety of outcomes e.g. DynamoDB and Cassandra restrict by variety of objects or rows. To tackle this, we use a static restrict for the preliminary queries to the backing retailer, question with this restrict, and course of the outcomes. If extra knowledge is required to fulfill the byte restrict, further queries are executed till the restrict is met, the surplus result&#8217;s discarded and a web page token is generated.<\/p>\n<p id=\"51d1\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">This static restrict can result in inefficiencies, one massive merchandise within the outcome might trigger us to discard many outcomes, whereas small objects might require a number of iterations to fill a web page, leading to learn amplification. To mitigate these points, we applied <em class=\"oz\">adaptive<\/em> pagination which dynamically tunes the boundaries based mostly on noticed knowledge.<\/p>\n<h2 id=\"6f49\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Adaptive Pagination<\/h2>\n<p id=\"d9f6\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">When an preliminary request is made, a question is executed within the storage engine, and the outcomes are retrieved. As the buyer processes these outcomes, the system tracks the variety of objects consumed and the full measurement used. This knowledge helps calculate an approximate merchandise measurement, which is saved within the web page token. For subsequent web page requests, this saved data permits the server to use the suitable limits to the underlying storage, decreasing pointless work and minimizing learn amplification.<\/p>\n<p id=\"c57f\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">While this technique is efficient for follow-up web page requests, what occurs with the preliminary request? In addition to storing merchandise measurement data within the web page token, the server additionally estimates the common merchandise measurement for a given namespace and caches it domestically. This cached estimate helps the server set a extra optimum restrict on the backing retailer for the preliminary request, bettering effectivity. The server repeatedly adjusts this restrict based mostly on latest question patterns or different elements to maintain it correct. For subsequent pages, the server makes use of each the cached knowledge and the knowledge within the web page token to fine-tune the boundaries.<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh qz\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*yg8xyQEoEmvKYoOV 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*yg8xyQEoEmvKYoOV 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*yg8xyQEoEmvKYoOV 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*yg8xyQEoEmvKYoOV 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*yg8xyQEoEmvKYoOV 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*yg8xyQEoEmvKYoOV 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*yg8xyQEoEmvKYoOV 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\/0*yg8xyQEoEmvKYoOV 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*yg8xyQEoEmvKYoOV 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*yg8xyQEoEmvKYoOV 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*yg8xyQEoEmvKYoOV 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*yg8xyQEoEmvKYoOV 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*yg8xyQEoEmvKYoOV 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/0*yg8xyQEoEmvKYoOV 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=\"bh me qo c\" width=\"700\" height=\"559\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"e11f\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">In addition to adaptive pagination, a mechanism is in place to ship a response early if the server detects that processing the request is vulnerable to exceeding the request\u2019s latency SLO.<\/p>\n<p id=\"8c43\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">For instance, allow us to assume a consumer submits a <code class=\"cx qd qe qf pv b\">GetItems<\/code> request with a per-page restrict of two MiB and a most end-to-end latency restrict of 500ms. While processing this request, the server retrieves knowledge from the backing retailer. This explicit file has hundreds of small objects so it will usually take longer than the 500ms SLO to assemble the complete web page of knowledge. If this occurs, the consumer would obtain an SLO violation error, inflicting the request to fail although there may be nothing distinctive. To stop this, the server tracks the elapsed time whereas fetching knowledge. If it determines that persevering with to retrieve extra knowledge would possibly breach the SLO, the server will cease processing additional outcomes and return a response with a pagination token.<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh ra\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*hEkIfkUJ4KDnbbGx 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*hEkIfkUJ4KDnbbGx 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*hEkIfkUJ4KDnbbGx 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*hEkIfkUJ4KDnbbGx 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*hEkIfkUJ4KDnbbGx 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*hEkIfkUJ4KDnbbGx 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*hEkIfkUJ4KDnbbGx 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\/0*hEkIfkUJ4KDnbbGx 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*hEkIfkUJ4KDnbbGx 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*hEkIfkUJ4KDnbbGx 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*hEkIfkUJ4KDnbbGx 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*hEkIfkUJ4KDnbbGx 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*hEkIfkUJ4KDnbbGx 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/0*hEkIfkUJ4KDnbbGx 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=\"bh me qo c\" width=\"700\" height=\"296\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"858e\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">This method ensures that requests are processed inside the SLO, even when the complete web page measurement isn\u2019t met, giving shoppers predictable progress. Furthermore, if the consumer is a gRPC server with correct deadlines, the consumer is sensible sufficient to not situation additional requests, decreasing ineffective work.<\/p>\n<p id=\"c909\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">If you need to know extra, the <a class=\"af nv\" href=\"https:\/\/www.infoq.com\/articles\/netflix-highly-reliable-stateful-systems\/\" rel=\"noopener ugc nofollow\" target=\"_blank\">How Netflix Ensures Highly-Reliable Online Stateful Systems<\/a> article talks in additional element about these and plenty of different methods.<\/p>\n<h2 id=\"c0c5\" class=\"pa nx gu bf ny pb pc dy oc pd pe ea og ni pf pg ph nm pi pj pk nq pl pm pn po bk\">Signaling<\/h2>\n<p id=\"2e5c\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">KV makes use of in-band messaging we name <em class=\"oz\">signaling<\/em> that enables the dynamic configuration of the consumer and allows it to speak its capabilities to the server. This ensures that configuration settings and tuning parameters might be exchanged seamlessly between the consumer and server. Without signaling, the consumer would wish static configuration \u2014 requiring a redeployment for every change \u2014 or, with dynamic configuration, would require coordination with the consumer group.<\/p>\n<p id=\"f164\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\">For server-side indicators, when the consumer is initialized, it sends a handshake to the server. The server responds again with indicators, similar to goal or max latency SLOs, permitting the consumer to dynamically alter timeouts and hedging insurance policies. Handshakes are then made periodically within the background to maintain the configuration present. For client-communicated indicators, the consumer, together with every request, communicates its capabilities, similar to whether or not it could deal with compression, chunking, and different options.<\/p>\n<figure class=\"pp pq pr ps pt qj qg qh paragraph-image\">\n<div role=\"button\" tabindex=\"0\" class=\"qk ql fj qm bh qn\">\n<div class=\"qg qh rb\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*sVOLoSeIKpzDMQ5N 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*sVOLoSeIKpzDMQ5N 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*sVOLoSeIKpzDMQ5N 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*sVOLoSeIKpzDMQ5N 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*sVOLoSeIKpzDMQ5N 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*sVOLoSeIKpzDMQ5N 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/format:webp\/0*sVOLoSeIKpzDMQ5N 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\/0*sVOLoSeIKpzDMQ5N 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*sVOLoSeIKpzDMQ5N 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*sVOLoSeIKpzDMQ5N 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*sVOLoSeIKpzDMQ5N 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*sVOLoSeIKpzDMQ5N 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*sVOLoSeIKpzDMQ5N 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1400\/0*sVOLoSeIKpzDMQ5N 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=\"bh me qo c\" width=\"700\" height=\"264\" loading=\"lazy\" role=\"presentation\"\/><\/picture><\/div>\n<\/div>\n<\/figure>\n<p id=\"18e7\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The KV abstraction powers a number of key Netflix use circumstances, together with:<\/p>\n<ul class=\"\">\n<li id=\"f38f\" class=\"mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Streaming Metadata<\/strong>: High-throughput, low-latency entry to streaming metadata, guaranteeing customized content material supply in real-time.<\/li>\n<li id=\"555b\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">User Profiles<\/strong>: Efficient storage and retrieval of consumer preferences and historical past, enabling seamless, customized experiences throughout gadgets.<\/li>\n<li id=\"61d8\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Messaging<\/strong>: Storage and retrieval of <a class=\"af nv\" rel=\"noopener ugc nofollow\" target=\"_blank\" href=\"https:\/\/netflixtechblog.com\/pushy-to-the-limit-evolving-netflixs-websocket-proxy-for-the-future-b468bc0ff658\">push registry<\/a> for messaging wants, enabling the thousands and thousands of requests to circulate via.<\/li>\n<li id=\"bcc9\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Real-Time Analytics<\/strong>: This persists large-scale impression and supplies insights into consumer conduct and system efficiency, <a class=\"af nv\" rel=\"noopener ugc nofollow\" target=\"_blank\" href=\"https:\/\/netflixtechblog.com\/bulldozer-batch-data-moving-from-data-warehouse-to-online-key-value-stores-41bac13863f8\">shifting knowledge from offline to on-line<\/a> and vice versa.<\/li>\n<\/ul>\n<p id=\"6a18\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">Looking ahead, we plan to reinforce the KV abstraction with:<\/p>\n<ul class=\"\">\n<li id=\"27c2\" class=\"mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Lifecycle Management<\/strong>: Fine-grained management over knowledge retention and deletion.<\/li>\n<li id=\"3282\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Summarization<\/strong>: Techniques to enhance retrieval effectivity by summarizing data with many objects into fewer backing rows.<\/li>\n<li id=\"249b\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">New Storage Engines<\/strong>: Integration with extra storage programs to help new use circumstances.<\/li>\n<li id=\"1ebe\" class=\"mx my gu mz b na qt nc nd ne qu ng nh ni qv nk nl nm qw no np nq qx ns nt nu qq qr qs bk\"><strong class=\"mz gv\">Dictionary Compression<\/strong>: Further decreasing knowledge measurement whereas sustaining efficiency.<\/li>\n<\/ul>\n<p id=\"b19f\" class=\"pw-post-body-paragraph mx my gu mz b na ou nc nd ne ov ng nh ni ow nk nl nm ox no np nq oy ns nt nu gn bk\">The Key-Value service at Netflix is a versatile, cost-effective resolution that helps a variety of knowledge patterns and use circumstances, from low to excessive site visitors eventualities, together with crucial Netflix streaming use-cases. The easy but strong design permits it to deal with numerous knowledge fashions like HashMaps, Sets, Event storage, Lists, and Graphs. It abstracts the complexity of the underlying databases from our builders, which allows our utility engineers to deal with fixing enterprise issues as an alternative of changing into specialists in each storage engine and their distributed <a class=\"af nv\" href=\"https:\/\/jepsen.io\/consistency\" rel=\"noopener ugc nofollow\" target=\"_blank\">consistency fashions<\/a>. As Netflix continues to innovate in on-line datastores, the KV abstraction stays a central part in managing knowledge effectively and reliably at scale, guaranteeing a strong basis for future development.<\/p>\n<p id=\"683f\" class=\"pw-post-body-paragraph mx my gu mz b na nb nc nd ne nf ng nh ni nj nk nl nm nn no np nq nr ns nt nu gn bk\"><strong class=\"mz gv\"><em class=\"oz\">Acknowledgments:<\/em><\/strong><em class=\"oz\"> Special because of our beautiful colleagues who contributed to Key Value\u2019s success: <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/william-schor\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">William Schor<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/mengqingwang\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Mengqing Wang<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/cthumuluru\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Chandrasekhar Thumuluru<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/rajiv-shringi\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Rajiv Shringi<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/john-l-693b7915a\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">John Lu<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/georgecampbell\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">George Cambell<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/akhaku\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Ammar Khaku<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/jordan-west-8aa1731a3\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Jordan West<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/clohfink\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Chris Lohfink<\/em><\/a><em class=\"oz\">, <\/em><a class=\"af nv\" href=\"https:\/\/www.linkedin.com\/in\/matt-lehman-39549719b\/\" rel=\"noopener ugc nofollow\" target=\"_blank\"><em class=\"oz\">Matt Lehman<\/em><\/a><em class=\"oz\">, and the entire on-line datastores group (ODS, f.ok.a CDE).<\/em><\/p>\n<\/div>\n<p>[ad_2]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] 13 min learn \u00b7 Sep 18, 2024 Vidhya Arvind, Rajasekhar Ummadisetty, Joey Lynch, Vinay Chella At Netflix our skill to ship seamless, high-quality, streaming experiences to thousands and thousands of customers hinges on strong, international backend infrastructure. Central to this infrastructure is our use of a number of on-line distributed databases similar to Apache [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":133466,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37],"tags":[6269,955,5086,4579,6268,5628,115,889,6185,4337],"class_list":{"0":"post-133464","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-netflix","8":"tag-abstraction","9":"tag-blog","10":"tag-data","11":"tag-introducing","12":"tag-keyvalue","13":"tag-layer","14":"tag-netflix","15":"tag-netflixs","16":"tag-sep","17":"tag-technology"},"_links":{"self":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/posts\/133464","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=133464"}],"version-history":[{"count":0,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/posts\/133464\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/media\/133466"}],"wp:attachment":[{"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/media?parent=133464"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/categories?post=133464"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/showbizztoday.com\/index.php\/wp-json\/wp\/v2\/tags?post=133464"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}