Chapter 1. API Architecture Primer
Anyone who has taken a long journey will no doubt have encountered the question (and possibly persistently) “are we there yet?”. For the first few inquiries we look at the GPS or a route planner and provide an estimate - hoping that we don’t encounter any delays along the way. The journey for an API Architect is usually complex and often coupled with changing infrastructure, cloud migration and possibly organizational change. Even in Greenfield projects, Type 1 Decisions 1 can have drastic consequences, despite seeming straightforward at the time. The ability for an API Architect to recognize and focus on key decisions is an important skill. An API Architect’s challenge does not stop here, in order to get internet scale and meet performance demands considering a microservices based architecture and horizontal scale will be necessary.
One of the challenges with architecture is in reality we are never there,2 or never quite where we planned to be. Trade offs are made in order to unlock value at different stages of the journey. For example, Service Mesh is a fantastic technology and is an enabler of a microservices based architecture and APIs. However, if your architecture began before Service Mesh was possible, what approach do you take? Do you stop and rebuild? The culminating effect of delivering incremental value combined with new emerging technologies leads to the concept of evolutionary architecture. Evolutionary Architectures are a critical idea we will embrace and discuss in the chapters to follow.
If we don’t have the API equivalent of a GPS system and expect our architecture to evolve, how do we best arrive at a system that is in the best possible state? In this book we will cover a variety of references, books and blogs for you to explore, whilst bringing together the context of why these topics are important to an API Architect. There are many media formats of information and everyone learns in a different way, finding the right approach for you personally will be an important balance to strike. As authors we came up with the idea of writing a book on API Architecture at the O’Reilly Software Architecture Conference in New York. In talking together and with other delegates we felt many key concepts of API architecture are covered extremely well independently, but often do not provide the big picture perspective of building out an API architecture. Although architects in different organizations are all travelling on different journeys, asking others for directions and challenging the planned route helps set us up for success.
In this chapter we will set the groundwork that will set us heading in the right direction for the rest of the book. We will explore key concepts and definitions and discuss how they fit within the context of an API architecture. We will introduce some tools and ideas for sharing architecture and decisions with other developers and architects. The chapter will close with the proposed architecture for our conference system, that we will discuss how to design and build throughout the book.
A Brief Introduction to APIs and Microservices Based Architecture
In the field of software architecture there are a handful of terms that are incredibly difficult to define.
The term API (Application Programming Interface) falls into this categorization, as the concept first surfaced as many as 80 years ago.
Broadly speaking APIs can be broken into two categories depending on whether the API invocation is in process or out of process.
For example, Java’s Date Time Library
java.util.time is a library provided by the core platform.
The invocation mechanism and data exchange is well defined, it is within the language constraints.
The invocation is compile time safe, so it is understood at the time of writing code the conditions under which the exchange mechanism will be successful.
An out of process exchange is significantly more complicated, the external process can be written in any language and potentially located across the world.
There needs to be an agreement on the protocol, expected behavior and compatibility.
This focuses on out of process exchange, in Chapter 2 we will explore many of the options available to us.
In the field of software architecture there are a handful of terms that are terribly named. Microservices is a term that is almost universally agreed as one of the most misleading names in our industry, the determination of size rarely comes into it. In the book we prefer the term Microservices Based Architecture, which involves the API Architect taking a pragmatic balance between Service Oriented Architecture and a Microservices Based Architecture. One thing we can agree on when it comes to Microservices is that there will be an increased number of services, looser coupling and a requirement to define interfaces and behavior between services.
The combination of Microservices Based Architecture, Public Cloud and APIs has lead to an explosion in demands for considering API Architectures. Designing for both elastic compute and expected failure has become more common with The Twelve-Factor App methodology. Although out of process exchange is not new, the paradigm shift over the recent years makes decoupled process interaction more important than before.
What is wrong with a monolithic approach?
It is possible to deliver an API Architecture using infrastructure routing and a monolithic service, and for smaller organizations this may be the best way to start. As the number of APIs offered and number of consumers increase, rapid bottlenecks in the process may start to form both in terms request latency and deploying new services. Chapter 6 will provide insights into the process of evolving existing services and will be worth considering for existing monolithic deployments.
Before we dive too far into what is the right type of deployment for our problem or drawing up an architecture proposal, we need to consider an important concept for API Architectures, traffic patterns.
Traffic Patterns: API Consumption From All Cardinal Points
Imagine walking into a coffee shop 5am on Broadway New York, mildly jet lagged and ordering a coffee. The barista takes your order and you pay, meanwhile a label is attached to the cup with your request and passed along to be fulfilled. Another barista picks up the cup and completes the request, handing it to you with warm or cold caffeinated goodness. You sit back and watch the world go by, and instead of the usual concurrency example with coffee shops you start to appreciate traffic patterns (or maybe that’s just us!).
Two more customers walks in (or ingresses) the coffee shop through the door with a request. The barista stops the first and checks what they want, the new customer is looking for waffles - which is not available. The barista turns them away 3, the next customer has a valid order. The order is passed along to be fulfilled by the hot beverage barista. Figure 1-1 displays the different interactions, lets formally define the flow of traffic through our system.
North-South Ingress Traffic
North-south, or ingress, traffic is network traffic entering (or “ingressing”) into a data center, network, or a Platform-as-a-Service (PaaS) or container orchestration cluster (e.g. Kubernetes). Traditional network diagrams were drawn with the ingress traffic entering the data center at the top of the page and flowing down (north to south) into the network, and the name has stuck. In our example this is the customer, entering through the door to make the request to the barista.
North-South Key Point: You Don’t Know the Client
Any location of your network that is exposed publicly will be accessed by unknown clients, often by design, and more often than not by clients you hadn’t intended. This means that any component handling north-south traffic must make valid assumptions about client identity and also include appropriate defenses. An API gateway that handles north-south traffic can often be the first line of defense (in depth) for an application and organization, and so security should be top priority: authentication, authorization, transport security, rate limiting etc.
East-West Service-to-Service Traffic
East-west, or service-to-service, traffic is network traffic flowing within a data center, network, PaaS, or cluster. Traditional network diagrams were drawn with the service-to-service (inter-data center) traffic flowing from left to right (east to west) in the diagrams. In our analogy this was the barista at the checkout handing the cup over to the cold beverage/hot beverage barista in order to be fulfilled. In turn the barista needs to request contents from other systems to fulfill the request.
East-West Key Point: Trust, But Verify
Most east-west traffic, particularly if the origin is within your IT estate, can be trusted to some degree. For example, it is often easier to implement mutual TLS (mTLS) within an organization’s network, and identity access management (IAM) and network access control lists (NACLs) have a smaller scope in comparison with dealing with the global (internet) context. However, this isn’t to say you can be lax with service-to-service security, as you still want to design applications and network architecture to make it hard for accidental issues (such as an internal denial of service by a broken service) or bad actors to cascade and move through your systems.
Cross-datacenter traffic is by no means a new concept — both on-premise/co-located infrastructure and cloud platforms have supported this since disaster recovery/business continuity (DR/BC) became a priority — but it has seen increased resurgence over the past several year with many of the service mesh technologies surfacing this as a first-class concept. So, you are probably asking yourself: is traffic flowing from one data center to another, or from one cluster to another, north-south traffic or east-west? You’ve asked a good question, and like all interesting software development questions that answer is “it depends”!
Generally speaking, if the traffic’s origin is trusted and the traffic is flowing over an internal network or over secured network (IPSec, VPNs, mTLS etc) it is often treated as east-west traffic. However, modern service mesh multi-cluster paradigms, such as service mirroring utilise an ingress controller (or API gateway) to route traffic that is egressing from one cluster to a service in another. So, here the traffic could be looked at as north-south. The best answer most likely points to the intent of the communication i.e. is the origin traffic from a trusted source and within some definition of “your” system.
Traffic Patterns and Traffic Management
Once we have a handle on our traffic patterns, the next challenge is how we manage traffic. Consider when it is 8am and the coffee shop is busy as people head to work, we’d want to be able to scale East→West services to handle the increase in traffic. Perhaps we want to deploy a new coffee machine that improves the speed coffee is dispensed, how do we ensure this machine isn’t overloaded whilst it is tested? This is where traffic management becomes and important concept in continuous delivery and deployments patterns in an API Architecture.
Different Types of API
API Architecture Taxonomy
The Open Systems Interconnection (OSI) Networking Model
Control Planes and Data Planes
API Architecture Toolbox
There are a lot of in-depth conversations about what makes a great architect and anti patterns in the role of an architect. The reality is that the size and maturity of the organization will determine what works best for individuals in this position. There are however several focus areas that the authors would recommend architects prioritize when evolving their API Architecture.
The ability to clearly communicate the architecture to stakeholders and the importance of components
When making decisions clearly record the decision, including the context and background for making the decision
Be amenable to an evolutionary architecture, work in the open and review the platform whilst continuing to deliver value
Aim to be aware of upcoming patterns and technologies from industry and have an unbiased forum to review and present ideas
When rolling out an API Architecture there will be stakeholders across infrastructure, security, devops, application development teams and of of course the API consumers too. This could be a few people in a smaller organization or thousands of people, depending on the organization and the consumers of the API. Regardless of the size of organization the authors believe there are several key tools to have in the architects toolbox.
Architecture Decision Records (ADR)
As developers, architects and indeed humans we have all been in the position where we ask the question “what were they thinking??”. If you have ever driven on the M62 between Leeds and Manchester in the United Kingdom you may have been baffled by the construction of the motorway. As you climb the hill on the 3 lane highway it starts to deviate away from the traffic contraflow, until eventually Scott Hall Farm emerges surrounded by around 15 acres of farming land nestled between the carriages. Local legend of what happened described the owner of the land as stubborn and refused to move or handover his land, so the engineers simply built around him 4 50 years later a documentary surfaced revealing that the real reason for this was a geological fault beneath the land, meaning the motorway had to be built that way. When people guess why something was done in particular way expect rumour, humour and possibly criticism to emerge.
In software architecture there will be many constraints that we have to build around, however we want to ensure the decision is recorded and transparent. Architecture Decision Records (ADRs) help make decisions clear in software architecture.
An Architecture Decision Record (ADR) is a document that captures a decision, including the context of how the decision was made and the consequences of adopting the decision.
Engineering at Spotify Blog
There are several templates available that help to capture ADRs consistently and group ADRs together. Some teams use a git repository and pull request new ADRs in, asking for feedback on the PR. Some companies keep ADRs centrally (or pull them from project repositories to a central location). The important thing to bear in mind is that a rejected ADR is probably more valuable than an accepted one, so ensuring they are available for comment and input is important.
The Unified Modeling Language (UML) provides an extensive dialect for communicating software architectures. A major challenge is that the vastness of what UML provides is not committed to memory of architects and developers, people quickly revert to boxes/circles/diamonds. It becomes a real challenge to understand the structure of diagrams before getting onto the technical content of the discussion. Many diagrams are only committed to a project history if someone accidentally uses a permanent marker instead of dry wipe marker by mistake.
The C4 Model provides a simplified set of diagrams that act as a guide to your project architecture at various different levels of detail. Context is an important part of reviewing a software architecture, and progressing through the series of diagrams is a progressive disclosure for the reader or during presentations.
Level 1: System Context
The System Context diagram is the big picture top level view of the software system. The technical details are not the focus here, but instead the aims of the software system and how it interacts with users and other dependencies of the system. This diagram should be understandable by both technical and non-technical stakeholders, it’s the diagram you would get out when speaking to any new team.
Level 2: Container Diagram
Once the context and overall big picture is established, the container diagram helps to look at the detailed breakout of the major participants in the architecture. A container is defined as “something that needs to be running in order for the overall system to work” for example a database or mobile application. The focus on these diagrams is technical in nature and builds on the context to discuss the technical implications. It is likely this diagram will be used in architecture reviews for feedback and discussion.
Level 3: Component Diagram
For each container, the component diagram discusses what makes up the containers functionality.
A component is really tricky to define, and it really does depend on what language/stack you are building upon.
If you are using Java this can be thought of a well defined interface that is used across the application - for example
Level 4: Code Diagram
The code diagram is where UML lives within the C4 model and entity relationship (ER) diagrams. Ideally this is an automatically generated diagram that gives the architect/developer full detail about the classes, interfaces in the container.
The astute reader may have noticed that the diagrams do not talk about infrastructure/deployment details and only talk about a single system. The C4 Model has a series of supplementary diagrams that will be extremely useful to provide some of the missing details that you may need to capture. For example, the System Landscape Diagram provides the context of the given system within other systems in the plant.
Lines and Arrow Heads
One of the most confusing parts of UML is the degree of complexity in the arrows and lines used within the diagram. In C4 an arrow represents a unidirectional relationship, which has a label that conveys the intent of the relationship between the entities. The goal should be that the reader can see there is a relationship and understand what it is for and why it is there at each level.
Lets practically explore the use of the C4 model by exploring the conference system example we will use throughout the book.
Conference System Example
As we continue to build later chapters of the book the example system is in flux and evolving to provide the best possible learning experience. In later early access releases we will add some of the diagrams here to introduce and explore the overall solution.