Netflix: How 'Separation of Concerns' Can Benefit Your API Design

This article was prepared by a guest contributor to ProgrammableWeb. The opinions expressed in this article are the author's own and do not necessarily reflect the view of ProgrammableWeb or its editorial staff.

Daniel Jacobson is the vice president of Netflix Edge Engineering, which handles the Netflix API and playback functionality. Prior to his time at Netflix, Jacobson was director of application development at NPR. There, he led the development of NPR’s digital properties, including the NPR API. Jacobson also recently co-authored the O’Reilly book “APIs: A Strategy Guide.” You can follow Daniel on Twitter or connect with him on LinkedIn.

In some of his more recent posts, he has written about upcoming transformations within the API space, ranging from orchestration layers to how Netflix pursued an optimized API design for the 1,000-plus device types that it supports. In this post, he will provide more context for these decisions and how they may (or, perhaps more likely, will) apply to your API designs--especially when it comes to the benefits of the separation-of-design model.

What do APIs do?

APIs do a lot of things, but, principally, they are responsible for three things: data gathering, data formatting and data delivery. Of course, APIs are responsible for a number of other things, as well—for example, security, discoverability and resiliency--but it’s all in support for the big three. For the purposes of API design, let's break down these three functions.

1. Data gathering is the process by which an API calls out to its data source(s) to retrieve whatever data is necessary to satisfy a request. In some cases, the data source could be a database accessed directly by the API server. In other cases, the API server could be accessing a range of backend distributed systems to gather bits of what it needs from each. Regardless of where the data source is, the data-gathering step is essential to satisfying a request--without it, there is no payload.

2. Once data has been gathered, the next step is data formatting in preparation for the response. There are many things that can happen in the formatting phase, including pruning of elements, transforming values, additional lookups, and retries for missing elements. Once the final bundle of elements is assembled and processed, it needs to be structured in concert with what the requesting agent expects. Whether that is through RSS, hierarchical JSON, flat XML, protocol buffers or some other payload structure, this is when the data gets manipulated according to certain specifications.

3. Data delivery is the act of transferring the formatted payload from the server to the requesting agent. Most often, this is accomplished through HTTP, and the full document will be delivered once processed completely by the server. It could, however, be handled in a variety of other ways, including streaming bits across the wire once gathered rather than waiting for the complete payload.

Separation of concerns

When considering these three responsibilities, it becomes clear that the API provider (that is, the team that produces and maintains the API) has a very different set of concerns than API consumers (that is, internal and/or external developers, UI teams and partners who make requests to the API). As shown in this chart, API providers care deeply about how data is gathered. API consumers have no vested interest in how gathering happens, as long as it happens. On the other hand, API consumers have their own concerns about what they are receiving and how it is to be received. That is, API consumers care about formatting and delivery methods, although there is likely a lot of diversity in how each consumer wants those functions carried out. API providers also have an interest in formatting and delivery, but that interest can be expressed in a very different way. The API provider cares about the format and delivery method only insofar as it affects the ability to handle the diverse needs expressed by API consumers.

Because both parties (API providers and API consumers) have an expressed interest in formatting and delivery, API providers most often provide a common, one-size-fits-all (OSFA) request/response model to which everyone must adhere. This makes it easier for the API provider to support virtually all API consumers, with the primary trade-off being that each API consumer has a serviceable, although not optimal, way to interact with the API. As I stated in a previous post, this OSFA model works great for a LSUDs (large sets of unknown developers) but not for SSKDs (small sets of known developers). As private APIs in support of mobile and device strategies continue to grow in prominence, we will continue to see the holes in this OSFA API design model.

Benefits for all involved

The better approach for handling API design for SSKDs is to create true separation of concerns, rather than have all server-side decisions made by the API provider. The API provider should be principally focused on designing systems that are excellent at data gathering. The systems should also be able to support, in some form, the ability for API consumers to define their own formatting and delivery options.

Handing off the formatting and delivery responsibilities to the consumers has tremendous benefits for all involved. It gets the API provider out of the business of trying to handle all of the nuanced formatting demands of a growing and diversifying set of consumers. Meanwhile, it liberates the API consumers from the rigid protocols that have been forced upon them, letting them define payloads that are optimal for the way they develop, deploy and test their code (while likely improving the processing of their UI code).

Let’s look at a couple of examples to see why this separation of concerns is important.

Some devices have hardware constraints, such as limited memory or a weaker CPU. Because of these limitations, a UI developer may prefer to have smaller payload sizes or a flatter object model that is easier for the CPU to parse. Meanwhile, some devices may have strict requirements. For example, a requirement for proprietary XML payloads may present a conflict with other devices that prefer to handle serialized JSON. Because of these differences, exacerbated by the tremendous growth in connected devices, separating out these concerns can play a significant role in development velocity and system reliability. Of course, there are many ways for API providers to enable API consumers to control formatting and delivery, which will be a design decision that needs to be discussed by all parties involved.

My team at Netflix and I have written a range of posts that clarify how we designed our system to support this separation of concerns. We believe that our model is quite strong, especially given the scale of the operation in handling more than 1,000 different device types, and we think it could be helpful for others, as well. Independent of the Netflix solution, as we continue to see the Internet of Things expand, more companies will aspire to get more content onto more platforms. Having a strong design that supports the separation of concerns will be an effective--and perhaps essential--tactic to help you get to where you want to go.

Comments(1)

This is somewhat incorrect. API's are an architectural cross cutting concern; as you follow the flow of an api call in your architecture, elements of the api (ie api processing/security/config) are used throughout the flow both in tooling and in application instances.

To properly abstract the api, you need to separate so that processing, security and configuration can be synced and reused across the architecture.