Introduction

In this introduction, you will discover the basics of APIs and their potential to be part of the architecture journey. We will introduce a lightweight definition for APIs and their use in and out of process. In order to demonstrate the importance of APIs, we will introduce the conference system case study, a running example that will evolve throughout the book. Out-of-process APIs allow you to think beyond a simple three-tiered architecture; we will introduce traffic patterns and their importance to demonstrate this. We will outline a summary of the case study steps, allowing you to skip ahead if an area is of interest to you straight away.

In order to present APIs and their associated ecosystem, we will use a series of important artifacts. We will introduce the case study with C4 model diagrams and revisit the specifics and logic behind the approach. You will also learn about the use of Architecture Decision Records (ADRs) and the value of clearly defining decisions across the software lifecycle. As the introduction closes, we will outline ADR Guidelines—our approach to help you make decisions when the answer is “it depends.”

The Architecture Journey

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, you look at the GPS or a route planner and provide an estimate—hoping that you don’t encounter any delays along the way. Similarly, the journey to building API-based architectures can be complex for developers and architects to navigate; even if there was an Architecture GPS, what would your destination be?

Architecture is a journey without a destination, and you cannot predict how technologies and architectural approaches will change. For example, you may not have been able to predict service mesh technology would become so widely used, but once you learn about its capabilities it may cause you to think about evolving your existing architecture. It is not only technologies that influence change in architecture; new business requirements and constraints also drive change in architectural direction.

The culminating effect of delivering incremental value combined with new emerging technologies leads to the concept of evolutionary architecture. Evolutionary architecture is an approach to incrementally changing an architecture, focusing on the ability to change with speed and reducing the risk of negative impacts. Along the way, we ask you to keep the following advice in approaching API architecture in mind:

Though architects like to be able to strategically plan for the future, the constantly changing software development ecosystem makes that difficult. Since we can’t avoid change, we need to exploit it.

Building Evolutionary Architectures by Neal Ford, Rebecca Parsons, and Patrick Kua (O’Reilly)

In many projects APIs themselves are evolutionary, requiring change as more systems and services are integrated. Most developers have built services that focus on a single function without considering the broader API reuse from a consumer perspective.

API-First design is an approach where developers and architects consider the functionality of their service and design an API in a consumer-centric manner. The API consumer could be a mobile application, another service, or even an external customer. In Chapter 1 we will review design techniques to support an API-First approach and discover how we build APIs that are durable to change and deliver value to a broad consumer base.

The good news is that you can start an API-driven architecture journey at any point. If you are responsible for preexisting technical inventory, we will show you techniques to evolve your architecture to promote the use of APIs in your platform. On the other hand, if you are lucky and have a blank canvas to work with, we will share with you the benefit of adopting API architectures based on our years of experience, while also highlighting key factors in decision making.

A Brief Introduction to APIs

In the field of software architecture, there are a handful of terms that are incredibly difficult to define. The term API, which stands for application programming interface, falls into this categorization, as the concept first surfaced as many as 80 years ago. Terms that have been around for a significant amount of time end up being overused and having multiple meanings in different problem spaces. We consider an API to mean the following:

  • An API represents an abstraction of the underlying implementation.

  • An API is represented by a specification that introduces types. Developers can understand the specifications and use tooling to generate code in multiple languages to implement an API consumer (software that consumes an API).

  • An API has defined semantics or behavior to effectively model the exchange of information.

  • Effective API design enables extension to customers or third parties for a business integration.

Broadly speaking, APIs can be broken into two general categories depending on whether the API invocation is in process or out of process. The process being referred to here is an operating system (OS) process. For example, a Java method invocation from one class to another is an in-process API invocation, as the call is handled by the same process from which the call was made. A .NET application invocating an external REST-like API using an HTTP library is an out-of-process API invocation, as the call is handled by an additional external process other than the process from which the call was made. Typically, an out-of-process API call will involve data traversing a network, potentially a local network, virtual private cloud (VPC) network, or the internet. We will focus on the latter style of APIs; however, architects will often encounter the requirement to remodel an in-process API to an out-of-process API. In order to demonstrate this concept (and others), we will create a running case study that will evolve throughout the book.

Running Example: Conference System Case Study

We have chosen to model a conference system for our case study because the domain is easily recognizable but also provides enough complexity for modeling an evolutionary architecture. Figure I-1 visualizes the conference system at the top level, allowing us to set the context of the architecture under discussion. The system is used by an external customer to create their attendee account, review the conference sessions available, and book their attendance.

maar 0001
Figure I-1. C4 conference system context diagram

Let’s zoom in to the conference system box in Figure I-2. Expanding the conference system provides us more detail about its major technical building blocks. The customer interacts with the web application, which invokes APIs on the conference application. The conference application uses SQL to query the backing datastore.

maar 1001
Figure I-2. C4 conference system container diagram

Figure I-2 reveals that from an API perspective the most interesting functionality is within the conference application container. Figure I-3 zooms in to this specific container, allowing you to explore the structure and interactions.

Four major components and the database are involved in the current system. The API Controller faces all incoming traffic from the UI and makes a decision about where to route the request in the system. This component would also be responsible for marshaling from the on the wire network-level representation to an object or representation in code. The API Controller component is intriguing from the perspective of in-process routing and acting as a junction point or front controller pattern. For API requests and processing, this is an important pattern; all requests pass through the controller, which makes a decision on where the request is directed. In Chapter 3 we will look at the potential for taking the controller out of process.

The Attendee, Booking, and Session components are involved in translating the requests into queries and execute SQL against the database out of process. In the existing architecture, the database is an important component, potentially enforcing relationships—for example, constraints between bookings and sessions.

maar 0003
Figure I-3. C4 conference system component diagram

Now that we have drilled down to the appropriate level of detail, let’s revisit the types of API interactions in the case study at this point.

Types of APIs in the Conference Case Study

In Figure I-3 the Web Application to API Controller arrow is an out-of-process call, whereas the API Controller to Attendee Component arrow is an example of an in-process call. All interactions within the Conference Application boundary are examples of in-process calls. The in-process invocation is well defined and restricted by the programming language used to implement the Conference Application. The invocation is compile-time safe (the conditions under which the exchange mechanism are enforced at the time of writing code).

Reasons for Changing the Conference System

The current architectural approach has worked for the conference system for many years, however the conference owner has asked for three improvements, which are driving architectural change:

  • The conference organizers would like to build a mobile application.

  • The conference organizers plan to go global with their system, running tens of conferences instead of one per year. In order to facilitate this expansion, they would like to integrate with an external Call for Papers (CFP) system for managing speakers and their application to present sessions at the conference.

  • The conference organizers would like to decommission their private data center and instead run the conference system on a cloud platform with global reach.

Our goal is to migrate the conference system to be able to support the new requirements, without impacting the existing production system or rewriting everything in one go.

From Tiered Architecture to Modeling APIs

The starting point of the case study is a typical three-tier architecture, composed of a UI, a server-side processing tier, and a datastore. To begin to discuss an evolutionary architecture we need a model to think about the way API requests are processed by the components. We need a model/abstraction that will work for both the public cloud, virtual machines in a data center and a hybrid approach.

The abstraction of traffic will allow us to consider out-of-process interactions between an API consumer and an API service, sometimes referred to as the API producer. With architectural approaches like service-oriented architecture (SOA) and microservices-based architecture, the importance of modeling API interactions is critical. Learning about API traffic and the style of communication between components will be the difference between realizing the advantages of increased decoupling or creating a maintenance nightmare.

Warning

Traffic patterns are used by data center engineers to describe network exchanges within data centers and between low-level applications. At the API level we are using traffic patterns to describe flows between groups of applications. For the purposes of this book, we are referring to application and API-level traffic patterns.

Case Study: An Evolutionary Step

To start to consider traffic pattern types, it will be useful to take a small evolutionary step in our case study architecture. In Figure I-4 a step has been taken to refactor the Attendee component into an independent service, as opposed to a package or module within the legacy conference system. The conference system now has two traffic flows: the interaction between the customer and the legacy conference system and the interaction between the legacy system and the attendee system.

maar 1002
Figure I-4. C4 conference system context—evolutionary step

North–south traffic

In Figure I-4 interaction between the customer and the legacy conference system is referred to a north–south traffic, and it represents an ingress flow. The customer is using the UI, which is sending requests to the legacy conference system over the internet. This represents a point in our network that is exposed publicly and will be accessed by the UI.1 This means that any component handling north–south traffic must make concrete checks about client identity and also include appropriate challenges before allowing traffic to progress through the system. Chapter 7 will go into detail about securing north–south API traffic.

East–west traffic

The new interaction between the legacy conference system and the Attendee service introduces an east–west traffic flow to our system. East–west traffic can be thought of as service-to-service style of communication within a group of applications. Most east–west traffic, particularly if the origin is within your wider infrastructure, can be trusted to some degree. Although we can trust the source of the traffic, it is still necessary to consider securing east–west traffic.

API Infrastructure and Traffic Patterns

There are two key infrastructure components present in API-based architectures, which are key to controlling traffic. Controlling and coordinating traffic is often described as traffic management. Generally north–south traffic will be controlled by API gateways, the key subject for Chapter 3.

East–west traffic will often be handled by infrastructure components like Kubernetes or service mesh, the key subject for Chapter 4. Infrastructure components like Kubernetes and service mesh use network abstractions to route to services, requiring services to run inside a managed environment. In some systems east–west traffic is managed by the application itself and service discovery techniques are implemented to locate other systems.

Roadmap for the Conference Case Study

Throughout the course of the book you will observe the following changes or applications of technology to the case study:

  • In Chapter 1 you will explore the design and specification of the Attendee API. We will also present the importance of versioning and modeling exchanges for performance of the Attendee API.

  • In Chapter 2 you will explore contract and component testing to verify behavior of the Attendee service. You will also see how Testcontainers can help with integration testing.

  • In Chapter 3 you will look at exposing the Attendee service to consumers using an API gateway. We will also demonstrate how to evolve the conference system using an API gateway on Kubernetes.

  • In Chapter 4 we will refactor the sessions functionality out of the legacy conference system using a service mesh. You will also learn about how service mesh helps with routing, observability, and security.

  • In Chapter 5 we will discuss feature flagging and how this can help to evolve the conference system and avoid a coupled deployment and release. You will also explore approaches for modeling releases in the conference system and we will demonstrate the use of Argo Rollouts for the Attendee service.

  • In Chapter 6 you will explore how to apply threat modeling and mitigate OWASP concerns in the Attendee service.

  • In Chapter 7 you will look at authentication and authorization and how this is implemented for the Attendee service.

  • In Chapter 8 you will look at establishing the Attendee service domain boundaries and how different service patterns can help.

  • In Chapter 9 you will look at cloud adoption and how to move the Attendee service to the cloud and consider replatforming.

The case study and the planned roadmap require us to visualize architectural change and record decisions. These are important artifacts that help to explain and plan changes in software projects. We believe that C4 diagrams and Architecture Decision Records (ADRs) represent a clear way of recording change.

Using C4 Diagrams

As part of introducing the case study, we revealed three types of C4 diagrams from the C4 model. We believe C4 is the best documentation standard for communicating architecture, context, and interactions to a diverse set of stakeholders. You may be wondering what about UML? The Unified Modeling Language (UML) provides an extensive dialect for communicating software architectures. A major challenge is that the majority of what UML provides is not committed to memory by architects and developers, and people quickly revert to boxes/circles/diamonds. It becomes a real challenge to understand the structure of diagrams before getting into 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 levels of detail.

C4 Context Diagram

Figure I-1 is represented using a C4 context diagram from the C4 model. The intention of this diagram is to set context for both a technical and nontechnical audience. Many architecture conversations dive straight into the low-level details and miss setting the context of the high-level interactions. Consider the implications of getting a system context diagram wrong—the benefit of summarizing the approach may save months of work to correct a misunderstanding.

C4 Container Diagram

While Figure I-1 provides the big picture of the conference system, a container diagram helps describe the technical breakout of the major participants in the architecture. A container in C4 is defined as “something that needs to be running in order for the overall system to work” (for example, the conference database). Container diagrams are technical in nature and build on the higher-level system context diagram. Figure I-2, a container diagram, documents the detail of a customer interacting with the conference system.

Note

The conference application container in Figure I-2 is documented as simply software. Normally a C4 container would provide more detail into the type of container (e.g., Java Spring Application). However in this book we will be avoiding technology specifics, unless it helps to demonstrate a specific solution. The advantage of APIs and indeed modern applications is that there is a significant amount of flexibility in the solution space.

C4 Component Diagram

The C4 component diagram in Figure I-3 helps to define the roles and responsibilities within each container, along with the internal interactions. This diagram is useful if the detail of a container is queried, and it also provides a very useful map to the codebase. Think about the first time starting work on a new project: browsing a self-documenting codebase is one approach—but it can be difficult to piece everything together. A component diagram reveals the detail of the language/stack you are using to build your software. In order to remain technology agnostic, we have used the term package/module.

Using Architecture Decision Records

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 three-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 refusing to move or hand over his land, so the engineers simply built around him.2 Fifty 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 a particular way, expect rumor, humor, and criticism to emerge.

In software architecture there will be many constraints that we have to build around, so it is important to ensure our decisions are recorded and transparent. ADRs help make decisions clear in software architecture.

One of the hardest things to track during the life of a project is the motivation behind certain decisions. A new person coming on to a project may be perplexed, baffled, delighted, or infuriated by some past decision.

Michael Nygard, creator of the ADR concept

There are four key sections in an ADR: status, context, decision, and consequences. An ADR is created in a proposed status and based on discussion will usually be either accepted or rejected. It is also possible that the decision may be superseded later by a new ADR. The context helps to set the scene and describe the problem or the bounds in which the decision will be made. Although creating a blog post ahead of the ADR and then linking from the ADR helps the community to follow your work, the context is not intended to be a blog post or detailed description. The decision clearly sets out what you plan to do and how you plan to do it. All decisions carry consequences or trade-offs in architecture, and these can sometimes be incredibly costly to get wrong.

When reviewing an ADR it is important to see if you agree with the decision in the ADR or if there is an alternative approach. An alternative approach that has not been considered may cause the ADR to be rejected. There is a lot of value in a rejected ADR and most teams choose to keep ADRs immutable to capture the change in perspective. ADRs work best when they are presented in a location where key participants can view them, comment, and help move the ADR to accepted.

Tip

A question we often get asked is at what point should the team create an ADR? It is useful to ensure that there has been discussion ahead of the ADR and the record is a result of collective thinking in the team. Publishing an ADR to the wider community allows the opportunity for feedback beyond the immediate team.

Attendees Evolution ADR

In Figure I-4 we made the decision to take an evolutionary step in the conference system architecture. This is a major change and would warrant an ADR. Table I-1 is an example ADR that might have been proposed by the engineering team owning the conference system.

Table I-1. ADR001 separating attendees from the legacy conference system
Status Proposed

Context

The conference owners have requested two new major features to the current conference system that need to be implemented without disrupting the current system. The conference system will need to be evolved to support a mobile application and an integration with an external CFP system. Both the mobile application and the external CFP system need to be able to access attendees to log in users to the third-party service.

Decision

We will take an evolutionary step as documented in Figure I-4 to split out the Attendee component into a standalone service. This will allow API-First development against the Attendee service and allow the API to be invoked from the legacy conference service. This will also support the ability to design for direct access to the Attendee service to provide user information to the external CFP system.

Consequences

The call to the Attendee service will not be out of process and may introduce a latency that will need to be tested. The Attendee service could become a single point of failure in the architecture and we may need to take steps to mitigate the potential impact of running a single Attendee service. With the planned multiple consumer model for the Attendee service, we will need to ensure good design, versioning, and testing to reduce accidental breaking changes.

Some of the consequences in the ADR are fairly major and definitely require further discussion. We are going to defer some of the consequences to later chapters.

Mastering API: ADR Guidelines

Within Mastering API Architecture we will be supplying ADR Guidelines to help collect important questions to ask when making decisions on the topic we are covering. Making decisions about an API-based architecture can be really tough, and in a lot of situations the answer is “it depends.” Rather than say it depends without context, the ADR Guidelines will help describe what it depends on and help inform your decisions. The ADR Guidelines can be used as a reference point to come back to or to read ahead to if you’re facing a specific challenge. Table I-2 outlines the format for the ADR Guidelines and what you should expect from them.

Table I-2. ADR Guideline: Format

Decision

Describes a decision that you might need to make when considering an aspect of this book.

Discussion Points

This section helps to identify the key discussions that you should be having when making a decision about your API architecture.

In this section we will reveal some of our experiences that may have influenced the decision. We will help you to identify the key information to inform your decision making process.

Recommendations

We will make specific recommendations that you should consider when creating your ADR, explaining the rationale behind why we are making a specific recommendation.

Summary

In this introduction we have provided a foundation with both the case study and the approach we will take to discussing API-driven architectures:

  • Architecture is an endless journey and APIs can play a major part in helping it evolve.

  • APIs are an abstraction of the implementation and can either be in process or out of process. Often architects find themselves in a position of evolving to out-of-process APIs, the onward focus of this book.

  • The conference case study is to describe and explain concepts. In this introduction you have seen a small evolutionary step to break out the Attendee service to address the upcoming business requirements.

  • You have seen the first three levels of C4 diagrams and their importance in sharing and communicating architecture.

  • ADRs provide a valuable record for making decisions and have both present and historical value in the lifetime of a project.

  • You have seen the structure for ADR Guidelines that will be used throughout the book to help facilitate decision making.

With the decision made to break the Attendee service out from the conference system, we will now explore the options for designing and specifying the Attendee API.

1 The intention is it will be the UI accessing the ingress point. However, it is open for potential exploit.

2 Local stubborn traits fueled this likely explanation.

Get Mastering API Architecture now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.