<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>distributed-systems &#8211; Noise</title>
	<atom:link href="https://noise.getoto.net/tag/distributed-systems/feed/" rel="self" type="application/rss+xml" />
	<link>https://noise.getoto.net</link>
	<description>The collective thoughts of the interwebz</description>
	<lastBuildDate>Tue, 21 Oct 2025 00:53:29 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.2</generator>
	<item>
		<title>Behind the Streams: Real-Time Recommendations for Live Events Part 3</title>
		<link>https://noise.getoto.net/2025/10/21/behind-the-streams-real-time-recommendations-for-live-events-part-3/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Tue, 21 Oct 2025 00:53:29 +0000</pubDate>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[live streaming]]></category>
		<category><![CDATA[Netflix]]></category>
		<guid isPermaLink="false">https://medium.com/p/e027cb313f8f</guid>

					<description><![CDATA[By: Kris Range, Ankush Gulati, Jim Isaacs, Jennifer Shin, Jeremy Kelly, Jason TuThis is part 3 in a series called “Behind the Streams”. Check out part 1 and part 2 to learn more.Picture this: It’s seconds before the biggest fight night in Netflix histo...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>100X Faster: How We Supercharged Netflix Maestro’s Workflow Engine</title>
		<link>https://noise.getoto.net/2025/09/29/100x-faster-how-we-supercharged-netflix-maestros-workflow-engine/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Mon, 29 Sep 2025 16:10:40 +0000</pubDate>
				<category><![CDATA[data]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[Orchestration]]></category>
		<category><![CDATA[workflow]]></category>
		<guid isPermaLink="false">https://medium.com/p/028e9637f041</guid>

					<description><![CDATA[By Jun He, Yingyi Zhang, Ely SpearsTL;DRWe recently upgraded the Maestro engine to go beyond scalability and improved its performance by 100X! The overall overhead is reduced from seconds to milliseconds. We have updated the Maestro open source project...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Building a Resilient Data Platform with Write-Ahead Log at Netflix</title>
		<link>https://noise.getoto.net/2025/09/26/building-a-resilient-data-platform-with-write-ahead-log-at-netflix/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Fri, 26 Sep 2025 18:57:07 +0000</pubDate>
				<category><![CDATA[database]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[message-queue]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[software-architecture]]></category>
		<guid isPermaLink="false">https://medium.com/p/127b6712359a</guid>

					<description><![CDATA[By Prudhviraj Karumanchi, Samuel Fu, Sriram Rangarajan, Vidhya Arvind, Yun Wang, John LuIntroductionNetflix operates at a massive scale, serving hundreds of millions of users with diverse content and features. Behind the scenes, ensuring data consisten...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Introducing Impressions at Netflix</title>
		<link>https://noise.getoto.net/2025/02/15/introducing-impressions-at-netflix/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Sat, 15 Feb 2025 01:13:20 +0000</pubDate>
				<category><![CDATA[data]]></category>
		<category><![CDATA[data-engineering]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<guid isPermaLink="false">https://medium.com/p/e2b67c88c9fb</guid>

					<description><![CDATA[Part 1: Creating the Source of Truth for ImpressionsBy: Tulika BhattImagine scrolling through Netflix, where each movie poster or promotional banner competes for your attention. Every image you hover over isn’t just a visual placeholder; it’s a critica...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Netflix’s Distributed Counter Abstraction</title>
		<link>https://noise.getoto.net/2024/11/12/netflixs-distributed-counter-abstraction/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Tue, 12 Nov 2024 20:45:23 +0000</pubDate>
				<category><![CDATA[counter]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[software-architecture]]></category>
		<category><![CDATA[system-design-interview]]></category>
		<guid isPermaLink="false">https://medium.com/p/8d0c45eb66b2</guid>

					<description><![CDATA[By: Rajiv Shringi, Oleksii Tkachuk, Kartik SathyanarayananIntroductionIn our previous blog post, we introduced Netflix’s TimeSeries Abstraction, a distributed service designed to store and query large volumes of temporal event data with low millisecond...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Java 21 Virtual Threads &#8211; Dude, Where’s My Lock?</title>
		<link>https://noise.getoto.net/2024/07/29/java-21-virtual-threads-dude-wheres-my-lock/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Mon, 29 Jul 2024 18:04:05 +0000</pubDate>
				<category><![CDATA[concurrency]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[troubleshooting]]></category>
		<guid isPermaLink="false">https://medium.com/p/3052540e231d</guid>

					<description><![CDATA[Getting real with virtual threadsBy Vadim Filanovsky, Mike Huang, Danny Thomas and Martin ChalupaIntroNetflix has an extensive history of using Java as our primary programming language across our vast fleet of microservices. As we pick up newer version...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Maestro: Netflix’s Workflow Orchestrator</title>
		<link>https://noise.getoto.net/2024/07/22/maestro-netflixs-workflow-orchestrator/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Mon, 22 Jul 2024 17:38:23 +0000</pubDate>
				<category><![CDATA[data]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[Orchestration]]></category>
		<category><![CDATA[workflow]]></category>
		<guid isPermaLink="false">https://medium.com/p/ee13a06f9c78</guid>

					<description><![CDATA[By Jun He, Natallia Dzenisenka, Praneeth Yenugutala, Yingyi Zhang, and Anjali NorwoodTL;DRWe are thrilled to announce that the Maestro source code is now open to the public! Please visit the Maestro GitHub repository to get started. If you find it usef...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Enhancing Netflix Reliability with Service-Level Prioritized Load Shedding</title>
		<link>https://noise.getoto.net/2024/06/26/enhancing-netflix-reliability-with-service-level-prioritized-load-shedding/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Tue, 25 Jun 2024 22:58:09 +0000</pubDate>
				<category><![CDATA[Chaos Engineering]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[load-shedding]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[reliability]]></category>
		<guid isPermaLink="false">https://medium.com/p/e735e6ce8f7d</guid>

					<description><![CDATA[Applying Quality of Service techniques at the application levelAnirudh Mendiratta, Kevin Wang, Joey Lynch, Javier Fernandez-Ivern, Benjamin FedorkaIntroductionIn November 2020, we introduced the concept of prioritized load shedding at the API gateway l...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Reverse Searching Netflix’s Federated Graph</title>
		<link>https://noise.getoto.net/2024/04/05/reverse-searching-netflixs-federated-graph/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 04 Apr 2024 21:26:42 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[Elasticsearch]]></category>
		<category><![CDATA[eventing]]></category>
		<category><![CDATA[GraphQL]]></category>
		<category><![CDATA[Search]]></category>
		<guid isPermaLink="false">https://medium.com/p/222ac5d23576</guid>

					<description><![CDATA[By Ricky Gardiner, Alex Hutter, and Katie LefevreSince our previous posts regarding Content Engineering’s role in enabling search functionality within Netflix’s federated graph (the first post, where we identify the issue and elaborate on the indexing ...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Sliding window rate limits in distributed systems</title>
		<link>https://noise.getoto.net/2023/12/14/sliding-window-rate-limits-in-distributed-systems/</link>
		
		<dc:creator><![CDATA[Grab Tech]]></dc:creator>
		<pubDate>Thu, 14 Dec 2023 00:00:10 +0000</pubDate>
				<category><![CDATA[Big Data]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Frequency capping]]></category>
		<category><![CDATA[Rate-limiting]]></category>
		<guid isPermaLink="false">https://engineering.grab.com/frequency-capping</guid>

					<description><![CDATA[Like many other companies, Grab uses marketing communications to notify users of promotions or other news. If a user receives these notifications from multiple companies, it would be a form of information overload and they might even start considering ...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>AVA Discovery View: Surfacing Authentic Moments</title>
		<link>https://noise.getoto.net/2023/08/18/ava-discovery-view-surfacing-authentic-moments/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 17 Aug 2023 22:07:14 +0000</pubDate>
				<category><![CDATA[computer vision]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[media-search]]></category>
		<guid isPermaLink="false">https://medium.com/p/b8cd145491cc</guid>

					<description><![CDATA[By: Hamid Shahid, Laura Johnson, Tiffany LowSynopsisAt Netflix, we have created millions of artwork to represent our titles. Each artwork tells a story about the title it represents. From our testing on promotional assets, we know which of these assets...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Migrating Netflix to GraphQL Safely</title>
		<link>https://noise.getoto.net/2023/06/14/migrating-netflix-to-graphql-safely/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Wed, 14 Jun 2023 17:59:46 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[GraphQL]]></category>
		<category><![CDATA[Migration]]></category>
		<category><![CDATA[Scale]]></category>
		<category><![CDATA[testing-tools]]></category>
		<guid isPermaLink="false">https://medium.com/p/8e1e4d4f1e72</guid>

					<description><![CDATA[By Jennifer Shin, Tejas Shikhare, Will EmmanuelIn 2022, a major change was made to Netflix’s iOS and Android applications. We migrated Netflix’s mobile apps to GraphQL with zero downtime, which involved a total overhaul from the client to the API layer...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Migrating Critical Traffic At Scale with No Downtime — Part 2</title>
		<link>https://noise.getoto.net/2023/06/13/migrating-critical-traffic-at-scale-with-no-downtime-part-2/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Tue, 13 Jun 2023 17:23:17 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[streaming]]></category>
		<category><![CDATA[system-migration]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://medium.com/p/4b1c8c7155c1</guid>

					<description><![CDATA[Migrating Critical Traffic At Scale with No Downtime — Part 2Shyam Gala, Javier Fernandez-Ivern, Anup Rokkam Pratap, Devang ShahPicture yourself enthralled by the latest episode of your beloved Netflix series, delighting in an uninterrupted, high-defin...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Ensuring the Successful Launch of Ads on Netflix</title>
		<link>https://noise.getoto.net/2023/06/01/ensuring-the-successful-launch-of-ads-on-netflix/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 01 Jun 2023 19:22:48 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[load-testing]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[sre]]></category>
		<guid isPermaLink="false">https://medium.com/p/f99490fdf1ba</guid>

					<description><![CDATA[By Jose Fernandez, Ed Barker, Hank JacobsIntroductionIn November 2022, we introduced a brand new tier — Basic with ads. This tier extended existing infrastructure by adding new backend components and a new remote call to our ads partner on the playback...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>ABAC on SpiceDB: Enabling Netflix’s Complex Identity Types</title>
		<link>https://noise.getoto.net/2023/05/19/abac-on-spicedb-enabling-netflixs-complex-identity-types/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Fri, 19 May 2023 12:01:47 +0000</pubDate>
				<category><![CDATA[authorization]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[software-architecture]]></category>
		<guid isPermaLink="false">https://medium.com/p/c118f374fa89</guid>

					<description><![CDATA[<p>By <a href="https://www.linkedin.com/in/chris-w-0a884022/">Chris Wolfe</a>, <a href="https://www.linkedin.com/in/joseph-s-4324904/">Joey Schorr</a>, and <a href="https://www.linkedin.com/in/vroldanbet/">Victor Roldán Betancort</a></p><h3>Introduction</h3><p>The authorization team at Netflix recently sponsored work to add Attribute Based Access Control (ABAC) support to AuthZed’s <a href="https://github.com/authzed/spicedb">open source Google Zanzibar inspired</a> authorization system, <a href="https://authzed.com/products/spicedb">SpiceDB</a>. Netflix required attribute support in SpiceDB to support core Netflix application identity constructs. This post discusses why Netflix wanted ABAC support in SpiceDB, how Netflix collaborated with AuthZed, the end result–<a href="https://authzed.com/docs/reference/caveats">SpiceDB Caveats</a>, and how Netflix may leverage this new feature.</p><p>Netflix is always looking for security, ergonomic, or efficiency improvements, and this extends to authorization tools. <a href="https://authzed.com/blog/what-is-google-zanzibar">Google Zanzibar</a> is exciting to Netflix as it makes it easier to produce authorization decision objects and reverse indexes for resources a principal can access.</p><p>Last year, while experimenting with Zanzibar approaches to authorization, Netflix found SpiceDB, the <a href="https://github.com/authzed/spicedb">open source Google Zanzibar inspired permission system</a>, and built a prototype to experiment with modeling. The prototype uncovered trade-offs required to implement Attribute Based Access Control in SpiceDB, which made it poorly suited to Netflix’s core requirements for application identities.</p><h3>Why did Netflix Want Caveated Relationships?</h3><p>Netflix application identities are fundamentally attribute based: e.g. an instance of the Data Processor runs in eu-west-1 in the test environment with a public shard.</p><p>Authorizing these identities is done not only by application name, but by specifying specific attributes on which to match. An application owner might want to craft a policy like “Application members of the EU data processors group can access a PI decryption key”. This is one normal relationship in SpiceDB. But, they might also want to specify a policy for compliance reasons that only allows access to the PI key from data processor instances running in the EU within a sensitive shard. Put another way, an identity should only be considered to have the “is member of the EU-data-processors group” if certain identity attributes (like region==eu) match in addition to the application name. This is a Caveated SpiceDB relationship.</p><h3>Netflix Modeling Challenges Before Caveats</h3><p>SpiceDB, being a Relationship Based Access Control (ReBAC) system, expected authorization checks to be performed against the existence of a specific relationship between objects. Users fit this model — they have a single user ID to describe who they are. As described above, Netflix applications do not fit this model. Their attributes are used to scope permissions to varying degrees.</p><p>Netflix ran into significant difficulties in trying to fit their existing policy model into relations. To do so Netflix’s design required:</p><ul><li>An event based mechanism that could ingest information about application autoscaling groups. An autoscaling group isn’t the lowest level of granularity, but it’s relatively close to the lowest level where we’d typically see authorization policy applied.</li><li>Ingest the attributes describing the autoscaling group and write them as separate relations. That is for the data-processor, Netflix would need to write relations describing the region, environment, account, application name, etc.</li><li>At authZ check time, provide the attributes for the identity to check, e.g. “can app bar in us-west-2 access this document.” SpiceDB is then responsible for figuring out which relations map back to the autoscaling group, e.g. name, environment, region, etc.</li><li>A cleanup process to prune stale relationships from the database.</li></ul><p>What was problematic about this design? Aside from being complicated, there were a few specific things that made Netflix uncomfortable. The most salient being that i<strong>t wasn’t resilient to an absence of relationship data, e.g. if a new autoscaling group started and reporting its presence to SpiceDB had not yet happened, the autoscaling group members would be missing necessary permissions to run</strong>. All this meant that Netflix would have to write and prune the relationship state with significant freshness requirements. This would be a significant departure from its existing policy based system.</p><p>While working through this, Netflix hopped into the SpiceDB Discord to chat about possible solutions and found an open community issue: the <a href="https://github.com/authzed/spicedb/issues/386">caveated relationships proposal</a>.</p><h3>The Beginning of SpiceDB Caveats</h3><p>The SpiceDB community had already explored <a href="https://github.com/authzed/spicedb/issues/158">integrating SpiceDB with Open Policy Agent (OPA)</a> and concluded it strayed too far from Zanzibar’s core promise of global horizontal scalability with strong consistency. With Netflix’s support, the AuthZed team pondered a Zanzibar-native approach to Attribute-Based Access Control.</p><p>The requirements were captured and published as the <a href="https://github.com/authzed/spicedb/issues/386">caveated relationships proposal on GitHub</a> for feedback from the SpiceDB community. The community’s excitement and interest became apparent through comments, reactions, and conversations on the <a href="https://authzed.com/discord">SpiceDB Discord server</a>. Clearly, Netflix wasn’t the only one facing challenges when reconciling SpiceDB with policy-based approaches, so Netflix decided to help! By sponsoring the project, Netflix was able to help AuthZed prioritize engineering effort and accelerate adding Caveats to SpiceDB.</p><h3>Building SpiceDB Caveats</h3><h4>Quick Intro to SpiceDB</h4><p>The <a href="https://authzed.com/docs/reference/schema-lang">SpiceDB Schema Language</a> lays the rules for how to build, traverse, and interpret SpiceDB’s Relationship Graph to make authorization decisions. SpiceDB Relationships, e.g., document:readme writer user:emilia, are stored as relationships that represent a graph within a datastore like CockroachDB or PostgreSQL. SpiceDB walks the graph and decomposes it into subproblems. These subproblems are assigned through <a href="https://authzed.com/blog/consistent-hash-load-balancing-grpc/">consistent hashing</a> and dispatched to a node in a cluster running SpiceDB. Over time, each node caches a subset of subproblems to support a distributed cache, reduce the datastore load, and achieve SpiceDB’s horizontal scalability.</p><h4>SpiceDB Caveats Design</h4><p>The fundamental challenge with policies is that their input arguments can change the authorization result as understood by a centralized relationships datastore. If SpiceDB were to cache subproblems that have been “tainted” with policy variables, the likelihood those are reused for other requests would decrease and thus severely affect the cache hit rate. As you’d suspect, this would jeopardize one of the pillars of the system: its ability to scale.</p><p>Once you accept that adding input arguments to the distributed cache isn’t efficient, you naturally gravitate toward the first question: what if you keep those inputs out of the cached subproblems? They are only known at request-time, so let’s add them as a variable in the subproblem! The cost of propagating those variables, assembling them, and executing the logic pales compared to fetching relationships from the datastore.</p><p>The next question was: how do you integrate the policy decisions into the relationships graph? The SpiceDB Schema Languages’ core concepts are <a href="https://authzed.com/docs/reference/glossary#relation">Relations</a> and <a href="https://authzed.com/docs/reference/glossary#permission">Permissions</a>; these are how a developer defines the shape of their relationships and how to traverse them. Naturally, being a graph, it’s fitting to add policy logic at the edges or the nodes. That leaves at least two obvious options: <strong>policy at the Relation level, or policy at the Permission level.</strong></p><p>After iterating on both options to get a feel for the ergonomics and expressiveness the choice was <strong>policy at the relation level</strong>. After all, SpiceDB is a Relationship Based Access Control (ReBAC) system. Policy at the relation level allows you to parameterize each relationship, which brought about the saying “this relationship exists, but with a Caveat!.” With this approach, SpiceDB could do request-time relationship vetoing like so:</p><pre>definition human {}<br><br>caveat the_answer(received int) {<br>  received == 42<br>}<br>definition the_answer_to_life_the_universe_and_everything {<br>  relation humans: human with the_answer<br>  permission enlightenment = humans</pre><p>Netflix and AuthZed discussed the concept of static versus dynamic Caveats as well. A developer would define static Caveat expressions in the SpiceDB Schema, while dynamic Caveats would have expressions defined at run time. The discussion centered around typed versus dynamic programming languages, but given SpiceDB’s Schema Language was designed for type safety, it seemed coherent with the overall design to continue with static Caveats. To support runtime-provided policies, the choice was to introduce expressions as arguments to a Caveat. Keeping the SpiceDB Schema easy to understand was a key driver for this decision.</p><p>For defining Caveats, the main requirement was to provide an expression language with first-class support for partially-evaluated expressions. <a href="https://github.com/google/cel-spec">Google’s CEL</a> seemed like the obvious choice: a protobuf-native expression language that evaluates in linear time, with first-class support for partial results that can be run at the edge, and is not turing complete. CEL expressions are type-safe, so they wouldn’t cause as many errors at runtime and can be stored in the datastore as a compiled protobuf. Given the near-perfect requirement match, it does make you wonder what Google’s Zanzibar has been up to since the white paper!</p><p>To execute the logic, SpiceDB would have to return a third response CAVEATED, in addition to ALLOW and DENY, to signal that a result of a CheckPermission request depends on computing an unresolved chain of CEL expressions.</p><p>SpiceDB Caveats needed to allow static input variables to be stored before evaluation to represent the multi-dimensional nature of Netflix application identities. Today, this is called “Caveat context,” defined by the values written in a SpiceDB Schema alongside a Relation and those provided by the client. Think of build time variables as an expansion of a templated CEL expression, and those take precedence over request-time arguments. Here is an example:</p><pre>caveat the_answer(received int, expected int) {<br>  received == expected<br>}</pre><p>Lastly, to deal with scenarios where there are multiple Caveated subproblems, the decision was to collect up a final CEL expression tree before evaluating it. The result of the final evaluation can be ALLOW, DENY, or CAVEATED. Things get trickier with wildcards and SpiceDB APIs, but let’s save that for another post! If the response is CAVEATED, the client receives a list of missing variables needed to properly evaluate the expression.</p><p>To sum up! The primary design decisions were:</p><ul><li>Caveats defined at the Relation-level, not the Permission-level</li><li>Keep Caveats in line with SpiceDB Schema’s type-safe nature</li><li>Support well-typed values provided by the caller</li><li>Use Google’s CEL to define Caveat expressions</li><li>Introduce a new result type: CAVEATED</li></ul><h3>How do SpiceDB Caveats Change Authorizing Netflix Identities?</h3><p><a href="https://authzed.com/docs/reference/caveats">SpiceDB Caveats</a> simplify this approach by allowing Netflix to specify authorization policy as they have in the past for applications. Instead of needing to have the entire state of the authorization world persisted as relations, the system can have relations and attributes of the identity used at authorization check time.</p><p>Now Netflix can write a Caveat similar to match_fine , described below, that takes lists of expected attributes, e.g. region, account, etc. This Caveat would allow the specific application named by the relation as long as the context of the authorization check had an observed account, stack, detail, region, and extended attribute values that matched the values in their expected counterparts. This <a href="https://play.authzed.com/s/51q8FOZ1PlzG/assertions">playground</a> has a live version of the schema, relations, etc. with which to experiment.</p><pre>definition app {}<br><br>caveat match_fine(<br>  expected_accounts list&#60;string&#62;,<br>  expected_regions list&#60;string&#62;,<br>  expected_stacks list&#60;string&#62;,<br>  expected_details list&#60;string&#62;,<br>  expected_ext_attrs map&#60;any&#62;,<br>  observed_account string,<br>  observed_region string,<br>  observed_stack string,<br>  observed_detail string,<br>  observed_ext_attrs map&#60;any&#62;<br>) {<br>  observed_account in expected_accounts &#38;&#38;<br>  observed_region in expected_regions &#38;&#38;<br>  observed_stack in expected_stacks &#38;&#38;<br>  observed_detail in expected_details &#38;&#38;<br>  expected_ext_attrs.isSubtreeOf(observed_ext_attrs)<br>}<br><br>definition movie {<br>  relation replicator: app with match_fine<br>  permission replicate = replicator<br>}</pre><p>Using this SpiceDB Schema we can write a relation to restrict access to the replicator application. It should only be allowed to run when</p><ul><li>It is in the highrisk or birdie accounts</li><li>AND in either us-west-1 or us-east-1</li><li>AND it has stack bg</li><li>AND it has detail casser</li><li>AND its extended attributes contain the key-value pair ‘foo: bar’</li></ul><pre>movie:newspecial#replicator@app:mover[match_fine:{"expected_accounts":["highrisk","birdie"],"expected_regions":["us-west-1","us-east-1"],"expected_stacks":["bg"],"expected_details":["casser"],"expected_ext_attrs":{"foo":"bar"}}]</pre><p>With the playground we can also make assertions that can mirror the behavior we’d see from the CheckPermission API. These assertions make it clear that our caveats work as expected.</p><pre>assertTrue:<br>- 'movie:newspecial#replicate@app:mover with {"observed_account": "highrisk", "observed_region": "us-west-1", "observed_stack": "bg", "observed_detail": "casser", "observed_ext_attrs": {"foo": "bar"}}'<br>assertFalse:<br>- 'movie:newspecial#replicate@app:mover with {"observed_account": "lowrisk", "observed_region": "us-west-1", "observed_stack": "bg", "observed_detail": "casser", "observed_ext_attrs": {"foo": "bar"}}'<br>- 'movie:newspecial#replicate@app:purger with {"observed_account": "highrisk", "observed_region": "us-west-1", "observed_stack": "bg", "observed_detail": "casser", "observed_ext_attrs": {"foo": "bar"}}'</pre><h3>Closing</h3><p>Netflix and AuthZed are both excited about the collaboration’s outcome. Netflix has another authorization tool it can employ and SpiceDB users have another option with which to perform rich authorization checks. Bridging the gap between policy based authorization and ReBAC is a powerful paradigm that is already benefiting companies looking to Zanzibar based implementations for modernizing their authorization stack.</p><h3>Acknowledgments</h3><ul><li><a href="https://www.linkedin.com/in/chris-w-0a884022/">Chris Wolfe</a></li><li><a href="https://www.linkedin.com/in/joseph-s-4324904/">Joey Schorr</a></li><li><a href="https://www.linkedin.com/in/vroldanbet/">Victor Roldán Betancort</a></li><li><a href="https://www.linkedin.com/in/chestonlee/">Cheston Lee</a></li></ul><h3>Additional Reading</h3><ul><li><a href="https://authzed.com/blog/what-is-google-zanzibar">What is Google Zanzibar</a></li><li><a href="https://authzed.com/zanzibar">Annotated Google Zanzibar Paper</a></li><li><a href="https://github.com/authzed/spicedb">SpiceDB, an Open Source, Google Zanzibar Inspired Authorization System</a></li><li><a href="https://github.com/google/cel-spec">Google’s CEL</a></li><li>SpiceDB <a href="https://authzed.com/docs/reference/glossary">Glossary</a></li><li><a href="https://authzed.com/blog/top-three-caveat-use-cases/">Top-3 Most Used SpiceDB Caveat Patterns (authzed.com)</a></li><li><a href="https://authzed.com/blog/check-it-out">How Permissions are Answered in SpiceDB</a></li><li><a href="https://play.authzed.com/s/51q8FOZ1PlzG">Netflix Complex Identities Example Schema</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&#38;referrerSource=full_rss&#38;postId=c118f374fa89" width="1" height="1" alt=""><hr><p><a href="https://netflixtechblog.com/abac-on-spicedb-enabling-netflixs-complex-identity-types-c118f374fa89">ABAC on SpiceDB: Enabling Netflix’s Complex Identity Types</a> was originally published in <a href="https://netflixtechblog.com/">Netflix TechBlog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Migrating Critical Traffic At Scale with No Downtime — Part 1</title>
		<link>https://noise.getoto.net/2023/05/05/migrating-critical-traffic-at-scale-with-no-downtime-part-1/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 04 May 2023 21:32:37 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[Netflix]]></category>
		<category><![CDATA[streaming]]></category>
		<category><![CDATA[system-migration]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://medium.com/p/ba1c7a1c7835</guid>

					<description><![CDATA[Migrating Critical Traffic At Scale with No Downtime — Part 1Shyam Gala, Javier Fernandez-Ivern, Anup Rokkam Pratap, Devang ShahHundreds of millions of customers tune into Netflix every day, expecting an uninterrupted and immersive streaming experience...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Building a Media Understanding Platform for ML Innovations</title>
		<link>https://noise.getoto.net/2023/03/14/building-a-media-understanding-platform-for-ml-innovations/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Tue, 14 Mar 2023 15:48:28 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[Search]]></category>
		<guid isPermaLink="false">https://medium.com/p/9bef9962dcb7</guid>

					<description><![CDATA[By Guru Tahasildar, Amir Ziai, Jonathan Solórzano-Hamilton, Kelli Griggs, Vi IyengarIntroductionNetflix leverages machine learning to create the best media for our members. Earlier we shared the details of one of these algorithms, introduced how our pl...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>NTS: Reliable Device Testing at Scale</title>
		<link>https://noise.getoto.net/2023/03/09/nts-reliable-device-testing-at-scale/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 09 Mar 2023 17:38:02 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[kafka]]></category>
		<category><![CDATA[testing]]></category>
		<guid isPermaLink="false">https://medium.com/p/43139ae05382</guid>

					<description><![CDATA[By Benson Ma, ZZ ZimmermanWith contributions from Alok Ahuja, Shravan Heroor, Michael Krasnow, Todor Minchev, Inder SinghIntroductionAt Netflix, we test hundreds of different device types every day, ranging from streaming sticks to smart TVs, to ensure...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Scaling Media Machine Learning at Netflix</title>
		<link>https://noise.getoto.net/2023/02/13/scaling-media-machine-learning-at-netflix/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Mon, 13 Feb 2023 17:59:51 +0000</pubDate>
				<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[mlops]]></category>
		<category><![CDATA[Netflix]]></category>
		<guid isPermaLink="false">https://medium.com/p/f19b400243</guid>

					<description><![CDATA[By Gustavo Carmo, Elliot Chow, Nagendra Kamath, Akshay Modi, Jason Ge, Wenbing Bai, Jackson de Campos, Lingyi Liu, Pablo Delgado, Meenakshi Jindal, Boris Chen, Vi Iyengar, Kelli Griggs, Amir Ziai, Prasanna Padmanabhan, and Hossein TaghaviFigure 1 - Med...]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
		<item>
		<title>Consistent caching mechanism in Titus Gateway</title>
		<link>https://noise.getoto.net/2022/11/03/consistent-caching-mechanism-in-titus-gateway/</link>
		
		<dc:creator><![CDATA[Netflix Technology Blog]]></dc:creator>
		<pubDate>Thu, 03 Nov 2022 19:19:31 +0000</pubDate>
				<category><![CDATA[container-orchestration]]></category>
		<category><![CDATA[distributed-cache]]></category>
		<category><![CDATA[distributed-systems]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[titus]]></category>
		<guid isPermaLink="false">https://medium.com/p/6cb89b9ce296</guid>

					<description><![CDATA[<p><em>by </em><a href="https://twitter.com/tomaszbak_ca"><em>Tomasz Bak</em></a><em> and </em><a href="https://twitter.com/fabiokung"><em>Fabio Kung</em></a></p><h3><strong>Introduction</strong></h3><p>Titus is the Netflix cloud container runtime that runs and manages containers at scale. In the time since it was <a href="https://netflixtechblog.com/titus-the-netflix-container-management-platform-is-now-open-source-f868c9fb5436">first presented</a> as an advanced Mesos framework, Titus has transparently evolved from being built on top of Mesos to Kubernetes, handling an ever-increasing volume of containers. As the number of Titus users increased over the years, the load and pressure on the system increased substantially. The original assumptions and architectural choices were no longer viable. This blog post presents how our current iteration of Titus deals with high API call volumes by scaling out horizontally.</p><p>We introduce a caching mechanism in the API gateway layer, allowing us to offload processing from singleton leader elected controllers without giving up strict data consistency and guarantees clients observe. Titus API clients always see the latest (not stale) version of the data regardless of which gateway node serves their request, and in which order.</p><h3><strong>Overview</strong></h3><p>The figure below depicts a simplified high-level architecture of a single Titus cluster (a.k.a cell):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RvGGmYT-CVWX7IgWJmMABQ.png"></figure><p><strong>Titus Job Coordinator</strong> is a leader elected process managing the active state of the system. Active data includes jobs and tasks that are currently running. When a new leader is elected it loads all data from external storage. Mutations are first persisted to the active data store before in-memory state is changed. Data for completed jobs and tasks is moved to the archive store first, and only then removed from the active data store and from the leader memory.</p><p><strong>Titus Gateway</strong> handles user requests. A user request could be a job creation request, a query to the active data store, or a query to the archive store (the latter handled directly in Titus Gateway). Requests are load balanced across all Titus Gateway nodes. All reads are consistent, so it does not matter which Titus Gateway instance is serving a query. For example, it is OK to send writes through one instance, and do reads from another one with full data read consistency guarantees. Titus Gateways always connect to the current Titus Job Coordinator leader. During leader failovers, all writes and reads of the active data are rejected until a connection to the active leader is re-established.</p><p>In the original version of the system, all queries to the active data set were forwarded to a singleton Titus Job Coordinator. The freshest data is served to all requests, and clients never observe <a href="https://en.wikipedia.org/wiki/Consistency_model#Session_guarantees">read-your-write or monotonic-read</a> consistency issues¹:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vo7yoEqsa9kAKCatcG4eeQ.png"></figure><p>Data consistency on the Titus API is highly desirable as it simplifies client implementation. Causal consistency, which includes read-your-writes and monotonic-reads, frees clients from implementing client-side synchronization mechanisms. In <a href="http://www.cs.umd.edu/~abadi/papers/abadi-pacelc.pdf">PACELC</a> terms we choose PC/EC and have the same level of availability for writes of our previous system while improving our theoretical availability for reads.</p><p>For example, a batch workflow orchestration system may create multiple jobs which are part of a single workflow execution. After the jobs are created, it monitors their execution progress. If the system creates a new job, followed immediately by a query to get its status, and there is a data propagation lag, it might decide that the job was lost and a replacement must be created. In that scenario, the system would need to deal with the data propagation latency directly, for example, by use of timeouts or client-originated update tracking mechanisms. As Titus API reads are always consistently reflecting the up-to-date state, such workarounds are not needed.</p><p>With traffic growth, a single leader node handling all request volume started becoming overloaded. We started seeing increased response latencies and leader servers running at dangerously high utilization. To mitigate this issue we decided to handle all query requests directly from Titus Gateway nodes but still preserve the original consistency guarantees:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qpVwpP4lqO42ARmzYZBXKA.png"></figure><p>The state from Titus Job Coordinator is replicated over a persistent stream connection, with low event propagation latencies. A new wire protocol provided by Titus Job Coordinator allows monitoring of the cache consistency level and guarantees that clients always receive the latest data version. The cache is kept in sync with the current leader process. When there is a failover (because of node failures with the current leader or a system upgrade), a new snapshot from the freshly elected leader is loaded, replacing the previous cache state. Titus Gateways handling client requests can now be horizontally scaled out. The details and workings of these mechanisms are the primary topics of this blog post.</p><h3><strong>How do I know that my cache is up to date?</strong></h3><p>It is an easy answer for systems that were built from the beginning with a consistent data versioning scheme and can depend on clients to follow the established protocol. Kubernetes is a good example here. Each object and each collection read from the Kubernetes cluster has a unique revision which is a monotonically increasing number. A user may request all changes since the last received revision. For more details, see <a href="https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions">Kubernetes API Concepts</a> and the <a href="https://github.com/kubernetes/client-go/blob/54928eef9f824667b23a938188498992d437156a/tools/cache/shared_informer.go#L35-L133">Shared Informer Pattern</a>.</p><p>In our case, we did not want to change the API contract and impose additional constraints and requirements on our users. Doing so would require a substantial migration effort to move all clients off the old API with questionable value to the affected teams (except for helping us solve Titus' internal scalability problems). In our experience, such migrations require a nontrivial amount of work, particularly with the migration timeline not fully in our control.</p><p>To fulfill the existing API contract, we had to guarantee that for a request received at a time T₀, the data returned to the client is read from a cache that contains all state updates in Titus Job Coordinator up to time T₀.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YysbNEvOfHhJXqwxIOsmLw.png"></figure><p>The path over which data travels from Titus Job Coordinator to a Titus Gateway cache can be described as a sequence of event queues with different processing speeds:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y5LMRFfNU8CZbVRNXIyBsw.png"></figure><p>A message generated by the event source may be buffered at any stage. Furthermore, as each event stream subscription from Titus Gateway to Titus Job Coordinator establishes a different instance of the processing pipeline, the state of the cache in each gateway instance may be vastly different.</p><p>Let’s assume a sequence of events E₁…E₁₀, and their location within the pipeline of two Titus Gateway instances at time T₁:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A-Arccp-E45UK0SOv8j7aw.png"></figure><p>If a client makes a call to Titus Gateway 2 at the time T₁, it will read version E₈ of the data. If it immediately makes a request to Titus Gateway 1, the cache there is behind with respect to the other gateway so the client might read an older version of the data.</p><p>In both cases, data is not up to date in the caches. If a client created a new object at time T₀, and the object value is captured by an event update E₁₀, this object will be missing in both gateways at time T₁. A surprise to the client who successfully completed a create request, but the follow-up query returned a not-found error (<a href="https://jepsen.io/consistency/models/read-your-writes">read-your-write</a> consistency violation).</p><p>The solution is to flush all the events created up to time T₁ and force clients to wait for the cache to receive them all. This work can be split into two different steps each with its own unique solution.</p><h3><strong>Implementation details</strong></h3><p>We solved the cache synchronization problem (as stated above) with a combination of two strategies:</p><ul><li>Titus Gateway &#60;-&#62; Titus Job Coordinator synchronization protocol over the wire.</li><li>Usage of high-resolution monotonic time sources like Java’s nano time within a single server process. Java’s nano time is used as a logical time within a JVM to define an order for events happening in the JVM process. An alternative solution based on an atomic integer values generator to order the events would suffice as well. Having the local logical time source avoids issues with <a href="https://en.wikipedia.org/wiki/Logical_clock">distributed clock synchronization</a>.</li></ul><p>If Titus Gateways subscribed to the Titus Job Coordinator event stream without synchronization steps, the amount of data staleness would be impossible to estimate. To guarantee that a Titus Gateway received all state updates that happened until some time Tₙ an explicit synchronization between the two services must happen. Here is what the protocol we implemented looks like:</p><ol><li>Titus Gateway receives a client request (queryₐ).</li><li>Titus Gateway makes a request to the local cache to fetch the latest version of the data.</li><li>The local cache in Titus Gateway records the local logical time and sends it to Titus Job Coordinator in a keep-alive message (<em>keep-aliveₐ</em>).</li><li>Titus Job Coordinator saves the keep-alive request together with the local logical time Tₐ of the request arrival in a local queue (<em>KAₐ, Tₐ</em>).</li><li>Titus Job Coordinator sends state updates to Titus Gateway until the former observes a state update (event) with a timestamp past the recorded local logical time (<em>E1, E2</em>).</li><li>At that time, Titus Job Coordinator sends an acknowledgment event for the keep-alive message (<em>KAₐ keep-alive ACK</em>).</li><li>Titus Gateway receives the keep-alive acknowledgment and consequently knows that its local cache contains all state changes that happened up to the time when the keep-alive request was sent.</li><li>At this point the original client request can be handled from the local cache, guaranteeing that the client will get a fresh enough version of the data (<em>responseₐ</em>).</li></ol><p>This process is illustrated by the figure below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m4zK_8tOTqTqrTEhY8mKaA.png"></figure><p>The procedure above explains how to synchronize a Titus Gateway cache with the source of truth in Titus Job Coordinator, but it does not address how the internal queues in Titus Job Coordinator are drained to the point where all relevant messages are processed. The solution here is to add a logical timestamp to each event and guarantee a minimum time interval between messages emitted inside the event stream. If not enough events are created because of data updates, a dummy message is generated and inserted into the stream. Dummy messages guarantee that each keep-alive request is acknowledged within a bounded time, and does not wait indefinitely until some change in the system happens. For example:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zOY7OU6LGLKLKfUeJhQp-Q.png"></figure><p><em>Ta</em>, <em>Tb</em>, <em>Tc</em>, <em>Td</em>, and <em>Te</em> are high-resolution monotonic logical timestamps. At time <em>Td</em> a dummy message is inserted, so the interval between two consecutive events in the event stream is always below a configurable threshold. These timestamp values are compared with keep-alive request arrival timestamps to know when a keep-alive acknowledgment can be sent.</p><p>There are a few optimization techniques that can be used. Here are those implemented in Titus:</p><ul><li>Before sending a keep-alive request for each new client request, wait a fixed interval and send a single keep-alive request for all requests that arrived during that time. So the maximum rate of keep-alive requests is constrained by 1 / max_interval. For example, if max_interval is set to 5ms, the max keep alive request rate is 200 req / sec.</li><li>Collapse multiple keep-alive requests in Titus Job Coordinator, sending a response to the latest one which has the arrival timestamp less than that of the timestamp of the last event sent over the network. On the Titus Gateway side, a keep-alive response with a given timestamp acknowledges all pending requests with keep-alive timestamps earlier or equal to the received one.</li><li>Do not wait for cache synchronization on requests that do not have ordering requirements, serving data from the local cache on each Titus Gateway. Clients that can tolerate eventual consistency can opt into this new API for lower response times and increased availability.</li></ul><p>Given the mechanism described so far, let’s try to estimate the maximum wait time of a client request that arrived at Titus Gateway for different scenarios. Let’s assume that the maximum keep alive interval is 5ms, and the maximum interval between events emitted in Titus Job Coordinator is 2ms.</p><p>Assuming that the system runs idle (no changes made to the data), and the client request arrives at a time when a new keep-alive request wait time starts, the cache update latency is equal to 7 milliseconds + network propagation delay + processing time. If we ignore the processing time and assume that the network propagation delay is &#60;1ms given we have to only send back a small keep-alive response, we should expect an 8ms delay in the typical case. If the client request does not have to wait for the keep-alive to be sent, and the keep-alive request is acknowledged immediately in Titus Job Coordinator, the delay is equal to network propagation delay + processing time, which we estimated to be &#60;1ms. The average delay introduced by cache synchronization <strong>is around 4ms</strong>.</p><p>Network propagation delays and stream processing times start to become a more important factor as the number of state change events and client requests increases. However, Titus Job Coordinator can now dedicate its capacity for serving high bandwidth streams to a finite number of Titus Gateways, relying on the gateway instances to serve client requests, instead of serving payloads to all client requests itself. Titus Gateways can then be scaled out to match client request volumes.</p><p>We ran empirical tests for scenarios of low and high request volumes, and the results are presented in the next section.</p><h3><strong>Performance test results</strong></h3><p>To show how the system performs with and without the caching mechanism, we ran two tests:</p><ul><li>A test with a low/moderate load showing a median latency increase due to overhead from the cache synchronization mechanism, but better 99th percentile latencies.</li><li>A test with load close to the peak of Titus Job Coordinator capacity, above which the original system collapses. Previous results hold, showing better scalability with the caching solution.</li></ul><p>A single request in the tests below consists of one query. The query is of a moderate size, which is a collection of 100 records, with a serialized response size of ~256KB. The total payload (request size times the number of concurrently running requests) requires a network bandwidth of ~2Gbps in the first test and ~8Gbps in the second one.</p><p><strong>Moderate load level</strong></p><p>This test shows the impact of cache synchronization on query latency in a moderately loaded system. The query rate in this test is set to 1K requests/second.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z5oih-LDS1rZ-x0TlgNtyQ.png"></figure><p>Median latency without caching is half of what we observe with the introduction of the caching mechanism, due to the added synchronization delays. In exchange, the worst-case 99th percentile latencies are 90% lower, dropping from 292 milliseconds without a cache to 30 milliseconds with the cache.</p><p><strong>Load level close to Titus Job Coordinator maximum</strong></p><p>If Titus Job Coordinator has to handle all query requests (when the cache is not enabled), it handles the traffic well up to 4K test queries / second, and breaks down (sharp latency increase and a rapid drop of throughput) at around 4.5K queries/sec. The maximum load test is thus kept at 4K queries/second.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ldai4UL3FTKWFIkGNkZQ-g.png"></figure><p>Without caching enabled the 99th percentile hovers around 1000ms, and the 80th percentile is around 336ms, compared with the cache-enabled 99th percentile at 46ms and 80th percentile at 22ms. The median still looks better on the setup with no cache at 17ms vs 19ms when the cache is enabled. It should be noted however that the system with caching enabled scales out linearly to more request load while keeping the same latency percentiles, while the no-cache setup collapses with a mere ~15% additional load increase.</p><p>Doubling the load when the caching is enabled does not increase the latencies at all. Here are latency percentiles when running 8K query requests/second:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FkTVLl8bYNz8zauMZf5yoA.png"></figure><h3>Conclusion</h3><p>After reaching the limit of vertical scaling of our previous system, we were pleased to implement a real solution that provides (in a practical sense) unlimited scalability of Titus read-only API. We were able to achieve better tail latencies with a minor sacrifice in median latencies when traffic is low, and gained the ability to horizontally scale out our API gateway processing layer to handle growth in traffic without changes to API clients. The upgrade process was completely transparent, and no single client observed any abnormalities or changes in API behavior during and after the migration.</p><p>The mechanism described here can be applied to any system relying on a singleton leader elected component as the source of truth for managed data, where the data fits in memory and latency is low.</p><p>As for prior art, there is ample coverage of cache coherence protocols in the literature, both in the context of multiprocessor architectures (<a href="https://ieeexplore.ieee.org/abstract/document/546611">Adve &#38; Gharachorloo, 1996</a>) and distributed systems (<a href="https://www.usenix.org/publications/library/proceedings/sd96/full_papers/seltzer.ps">Gwertzman &#38; Seltzer, 1996</a>). Our work fits within mechanisms of client polling and invalidation protocols explored by Gwertzman and Seltzer (1996) in their survey paper. Central timestamping to facilitate linearizability in read replicas is similar to the <a href="https://cs.yale.edu/homes/thomson/publications/calvin-sigmod12.pdf">Calvin</a> system (example real-world implementations in systems like <a href="https://www.foundationdb.org/files/fdb-paper.pdf">FoundationDB</a>) as well as the replica watermarking in AWS <a href="https://web.stanford.edu/class/cs245/readings/aurora.pdf">Aurora</a>.</p><p>¹ <a href="https://dataintensive.net/">Designing Data-Intensive Applications</a> is an excellent book that goes into detail about consistency models discussed in this blog post.</p><p>² Adve, S. V., &#38; Gharachorloo, K. (1996). Shared memory consistency models: A tutorial. computer, 29(12), 66–76.</p><p>³ Gwertzman, J., &#38; Seltzer, M. I. (1996, January). World Wide Web Cache Consistency. In USENIX annual technical conference (Vol. 141, p. 152).</p><img src="https://medium.com/_/stat?event=post.clientViewed&#38;referrerSource=full_rss&#38;postId=6cb89b9ce296" width="1" height="1" alt=""><hr><p><a href="https://netflixtechblog.com/consistent-caching-mechanism-in-titus-gateway-6cb89b9ce296">Consistent caching mechanism in Titus Gateway</a> was originally published in <a href="https://netflixtechblog.com/">Netflix TechBlog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></description>
		
		
		<enclosure url="" length="0" type="" />

			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Object Caching 39/329 objects using Memcached
Page Caching using Disk: Enhanced 
Lazy Loading (feed)
Database Caching using Memcached

Served from: noise.getoto.net @ 2025-12-11 21:00:11 by W3 Total Cache
-->