AW Patterns For API Design
AW Patterns For API Design
“The authors have captured design patterns across the API lifecycle, from definition
to design, in an approachable way. Whether you have designed dozens of web APIs or
you are just starting out, this book is a valuable resource to drive consistency and
overcome any design challenge you may face. I highly recommend this book!”
—James Higginbotham
Author of Principles of Web API Design: Delivering value with APIs and
Microservices and Executive API Consultant, LaunchAny
“APIs are everywhere in today’s software development landscape. API design looks
easy but, as anyone who has suffered a poorly designed API will attest, it is a difficult
skill to master and much subtler and more complex than it initially appears. In this
book, the authors have used their long experience and years of research work to cre-
ate a structured body of knowledge about API design. It will help you to understand
the underlying concepts needed to create great APIs and provides a practical set of
patterns that you can use when creating your own APIs. It is recommended for any-
one involved in the design, building, or testing of modern software systems.”
Application programming interfaces (API) are among the top priority elements to help
manage many of the trade-offs involved in system design, in particular distributed sys-
tems, which increasingly dominate our software ecosystem. In my experience, this
book removes the complexities in understanding and designing APIs with concepts
accessible to both practicing engineers and those who are just starting their software
engineering and architecting journey. All who aspire to play a key role in system design
should understand the API design concepts and patterns presented in this book.”
—Ipek Ozkaya
Technical Director, Engineering Intelligence Software System
Software Solutions Division
Carnegie Mellon University Software Engineering Institute
Editor-in-Chief 2019–2023 IEEE Software Magazine
“It is my belief that we are entering into an era where API-first design will become
the dominant form of design in large, complex systems. For this reason, Patterns for
API Design is perfectly timed and should be considered essential reading for any
architect.”
“The book Patterns for API Design is the Swiss army knife for software engineers
and architects when it comes to designing, evolving, and documenting APIs. What I
particularly like about the book is that it does not just throw the patterns at the
reader; instead, the authors use realistic examples, provide hands-on architecture
decision support, and exemplify patterns and decisions using a case study. As a
result, their pattern language is very accessible. You can use the book to find solu-
tions for specific problems or browse entire chapters to get an overview of the prob-
lem and solution spaces related to API design. All patterns are well-crafted,
well-named, and peer-reviewed by the practitioner community. It’s a joy.”
Olaf Zimmermann
Mirko Stocker
Daniel Lübke
Uwe Zdun
Cesare Pautasso
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where
those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed
with initial capital letters or in all capitals.
The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any
kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in
connection with or arising out of the use of the information or programs contained herein.
For information about buying this title in bulk quantities, or for special sales opportunities (which may include electronic
versions; custom cover designs; and content particular to your business, training goals, marketing focus, or branding
interests), please contact our corporate sales department at [email protected] or (800) 382-3419.
For questions about sales outside the U.S., please contact [email protected].
All rights reserved. This publication is protected by copyright, and permission must be obtained from the publisher prior
to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic,
mechanical, photocopying, recording, or likewise. For information regarding permissions, request forms and the appropriate
contacts within the Pearson Education Global Rights & Permissions Department, please visit www.pearson.com/permissions.
ISBN-13: 978-0-13-767010-9
ISBN-10: 0-13-767010-9
ScoutAutomatedPrintCode
Pearson’s Commitment to Diversity, Equity, and Inclusion
Pearson is dedicated to creating bias-free content that reflects the diversity of all learners. We
embrace the many dimensions of diversity, including but not limited to race, ethnicity, gender,
socioeconomic status, ability, age, sexual orientation, and religious or political beliefs.
Education is a powerful force for equity and change in our world. It has the potential to
deliver opportunities that improve lives and enable economic mobility. As we work with authors
to create content for every product and service, we acknowledge our responsibility to demonstrate
inclusivity and incorporate diverse scholarship so that everyone can achieve their potential
through learning. As the world’s leading learning company, we have a duty to help drive change
and live up to our purpose to help more people create a better life for themselves and to create a
better world.
Our ambition is to purposefully contribute to a world where:
While we work hard to present unbiased content, we want to hear from you about any
concerns or needs with this Pearson product so that we can investigate and address them.
xi
xii Contents
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
Foreword by Vaughn Vernon,
Series Editor
xvii
xviii Foreword by Vaughn Vernon, Series Editor
That’s where this series comes into play. I am curating a series designed to help
you mature and reach greater success with a variety of approaches—reactive, object,
and functional architecture and programming; domain modeling; right-sized ser-
vices; patterns; and APIs. And along with that, the series covers best uses of the asso-
ciated underlying technologies. It’s not accomplished in one fell swoop. It requires
organic refinement with purpose and skill. I and the other authors are here to help.
To that end, we’ve delivered our very best to achieve our goal.
Now, back to my story. When Olaf and I first met, I offered for him and Stefan to
attend my IDDD Workshop a few weeks later in Munich, Germany. Although nei-
ther were able to break away for all three days, they were open to attend the third and
final day. My second offer was for Olaf and Stefan to use time after the workshop to
demonstrate the Context Mapper tool. The workshop attendees were impressed, as
was I. This led to further collaboration on into 2020. Little did any of us expect what
that year would bring. Even so, Olaf and I were able to meet somewhat frequently to
continue design discussions about Context Mapper. During one of these meetings,
Olaf mentioned his work on API patterns that were provided openly. Olaf showed
me a number of patterns and additional tooling he and others had built around
them. I offered Olaf the opportunity to author in the series. The result is now in
front of you.
I later met on a video call with Olaf and Daniel Lübke to kick off product devel-
opment. I have not had the chance to spend time with the other authors—Mirko
Stocker, Uwe Zdun, Cesare Pautasso—but I was assured of the team’s quality given
their credentials. Notably, Olaf and James Higginbotham collaborated to ensure the
complementary outcome of this book and Principles of Web API Design, also in this
series. As an overall result, I am very impressed with what these five have contributed
to the industry literature. API design is a very important topic. The enthusiasm
toward the book’s announcement proves that it is right in the topic’s sweet spot. I am
confident that you will agree.
—Vaughn Vernon, series editor
This page intentionally left blank
Foreword by Frank Leymann
APIs are everywhere. The API economy enables innovation in technology areas,
including cloud computing and the Internet of Things (IoT), and is also a key ena-
bler of digitalization of many companies. There hardly is any enterprise application
without external interfaces to integrate customers, suppliers, and other business
partners; solution-internal interfaces decompose such applications into more man-
ageable parts, such as loosely coupled microservices. Web-based APIs play a promi-
nent role in these distributed settings but are not the only way to integrate remote
parties: queue-based messaging channels as well as publish/subscribe-based channels
are widely used for backend integration, exposing APIs to message producers and
consumers. gRPC and GraphQL have gained a lot of momentum as well. Thus, best
practices for designing “good” APIs are desirable. Ideally, API designs persist across
technologies and survive when those change.
Patterns establish a vocabulary for a problem-solution domain, finding a balance
between being abstract and concrete, which gives them both timelessness and rele-
vance today. Take Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf
from the Addison Wesley Signature Series as an example: I have been using it in
teaching and industry assignments since my time as lead architect of the IBM MQ
family of products. Messaging technologies come and, sometimes, go—but the mes-
saging concepts such as Service Activator and Idempotent Receiver are here to stay. I
have written cloud computing patterns, IoT patterns, quantum computing patterns,
even patterns for patterns in digital humanities myself. And Martin Fowler’s Patterns
of Enterprise Application Architecture, also from the Addison Wesley Signature
Series, gives us the Remote Façade and the Service Layer. Hence, many parts of the
overall design space of distributed applications are covered well in this literature—
but not all. Therefore, it is great to see that the API design space is now supported by
patterns too, the request and response messages that travel between API client and
API provider in particular.
The team who wrote this book is a great mix of architects and developers com-
posed of deeply experienced industry professionals, leaders in the patterns commu-
nity, and academic researchers and lecturers. I have been working with three of the
authors of this book for many years and have been following their MAP project since
its inception in 2016. They apply the pattern concept faithfully: Each pattern text
follows a common template that takes us from a problem context, including design
forces, to a conceptual solution. It also comes with a concrete example (often
xxi
xxii Foreword by Frank Leymann
RESTful HTTP). A critical discussion of pros and cons resolves the initial design
forces and closes with pointers to related patterns. Many of the patterns went
through shepherding and writers workshops at pattern conferences, which helped to
incrementally and iteratively improve and harden them over several years, capturing
collective knowledge as a result from this process.
This book provides multiple perspectives on the API design space, from scoping
and architecture to message representation structure and quality attribute-driven
design to API evolution. Its pattern language can be navigated via different paths,
including project phases and structural elements such as API endpoint and opera-
tion. As in our Cloud Computing Patterns book, a graphical icon for each pattern
conveys its essence. These icons serve as mnemonics and can be used to sketch APIs
and their elements. The book takes a unique and novel step in providing decision
models that collect recurring questions, options, and criteria regarding pattern
applications. They provide stepwise, easy-to-follow design guidance without over-
simplifying the complexities inherent to API design. A stepwise application to a sam-
ple case makes the models and their advices tangible.
In Part 2, the patterns reference, application and integration architects will find
the coverage of endpoint roles such as Processing Resource and operation responsi-
bilities such as State Transition Operation useful to size APIs adequately and make
(cloud) deployment decisions. State matters, after all, and several patterns make
state management behind the API curtain explicit. API developers will benefit from
the careful consideration given to identifiers (in patterns such as API Key and Id Ele-
ment), several options for response shaping (for instance, with Wish Lists and a Wish
Template that abstracts from GraphQL), and pragmatic advice on how to expose
metadata of different kinds.
I have not seen life-cycle management and versioning strategies captured in pattern
form in other books so far. Here, we can learn about Limited Lifetime Guarantees and
Two in Production, two patterns very common in enterprise applications. These evolu-
tion patterns will be appreciated by API product owners and maintainers.
In summary, this book provides a healthy mix of theory and practice, containing
numerous nuggets of deep advice but never losing the big picture. Its 44 patterns,
organized in five categories and chapters, are grounded in real-world experience and
documented with academic rigor applied and practitioner-community feedback
incorporated. I am confident that these patterns will serve the community well,
today and tomorrow. API designers in industry as well as in research, development,
and education related to API design and evolution can benefit from them.
• The context and the purpose of the book—its motivation, goals and scope.
• Who should read the book—our target audience with their use cases and
information needs.
• How the book is organized, with patterns serving as knowledge vehicles.
Motivation
Humans communicate in many different languages. The same holds for software.
Software not only is written in various programming languages but also communi-
cates via a plethora of protocols (such as HTTP) and message exchange formats
(such as JSON). HTTP, JSON, and other technologies operate every time somebody
updates their social network profile, orders something in a Web shop, swipes their
credit card to purchase something, and so on:
xxiii
xxiv Preface
API clients consume the services exposed by API providers. API documentation gov-
erns the client-provider interactions.
Just like humans, software components often struggle to understand each other
when they communicate; it is hard for their designers to decide on an adequate size and
structure of message content and agree on the best-suited conversation style. Neither
party wants to be too quiet or overly talkative when articulating its needs or responding
to requests. Some application integration and API designs work very well; the involved
parties understand each other and reach their goals. They interoperate effectively and
efficiently. Others lack clarity and thereby confuse or stress participants; verbose mes-
sages and chatty conversations may overload the communication channels, introduce
unnecessary technical risk, and cause extra work in development and operations.
Now, what distinguishes good and poor integration API designs? How can API
designers stimulate a positive client developer experience? Ideally, the guidelines for
good integration architectures and API designs do not depend on any particular
technology or product. Technologies and products come and go, but related design
advice should stay relevant for a long time. In our real-world analogy, principles such
as those of Cicero’s rhetoric and eloquence or Rosenberg’s in Nonviolent Communi-
cation: A Language of Life [Rosenberg 2002] are not specific to English or any other
natural language; they will not go out of fashion as natural languages evolve. Our
book aims to establish a similar toolbox and vocabulary for integration specialists
and API designers. It presents its knowledge bits as patterns for API design and evo-
lution that are eligible under different communication paradigms and technologies
(with HTTP- and JSON-based Web APIs serving as primary sources of examples).
While much has been said and written about HTTP, Web APIs, and integration
architectures in general (including service-oriented ones), the design of individual
API endpoints and message exchanges has received less attention so far:
• How many API operations should be exposed remotely? Which data should be
exchanged in request and response messages?
Preface xxv
The patterns in this book help answer these questions by sketching proven solu-
tions to specific design problems recurring in certain requirements contexts. Focus-
ing on remote APIs (rather than program-internal ones), they aim at improving the
developer experience on both the client side and the provider side.
Target Audience
This book targets intermediate-level software professionals striving to improve their
skills and designs. The presented patterns primarily aim at integration architects,
API designers, and Web developers interested in platform-independent architectural
knowledge. Both backend-to-backend integration specialists and developers of APIs
supporting frontend applications can benefit from the knowledge captured in the
patterns. As we focus on API endpoint granularity and the data exchanged in mes-
sages, additional target roles are API product owner, API reviewer, and cloud tenant
and provider.
This book is for you if you are a medium-experienced software engineer (such
as developer, architect, or product owner) already familiar with API funda-
mentals and want to improve your API design capabilities, including message
data contract design and API evolution.
Students, lecturers, and software engineering researchers may find the patterns
and their presentation in this book useful as well. We provide an introduction to API
fundamentals and a domain model for API design to make the book and its patterns
understandable without first having to read a book for beginners.
xxvi Preface
Knowing about the available patterns and their pros and cons will improve profi-
ciency regarding API design and evolution. APIs and the services they provide will be
simpler to develop, consume, and evolve when applying patterns from this book
suited for a particular requirements context.
Usage Scenarios
Our objective is to make API design and usage a pleasant experience. To that end,
three main use cases for our book and its patterns are as follows:
1. Facilitate API design discussions and workshops by establishing a common
vocabulary, pointing out required design decisions, and sharing available
options and related trade-offs. Empowered by this knowledge, API providers
are enabled to expose APIs of quality and style that meet their clients’ needs,
both short term and long term.
2. Simplify API design reviews and speed up objective API comparisons so that
APIs can be quality assured—and evolved in a backward-compatible and
extensible way.
3. Enhance API documentation with platform-neutral design information so that
API client developers can grasp the capabilities and constraints of provided
APIs with ease. The patterns are designed to be embeddable into API contracts
and observable in existing designs.
We provide a fictitious case study and two real-world pattern adoption stories to
demonstrate and jumpstart this pattern usage.
We do not expect readers to know any particular modeling approach, design tech-
nique, or architectural style already. However, such concepts—for instance, the
Align-Define-Design-Refine (ADDR) process, domain-driven design (DDD), and
responsibility-driven design (RDD)—have their roles to play. They are reviewed
briefly in Appendix A.
Patterns are not invented but are mined from practical experience and then hard-
ened via peer feedback. The patterns community has developed a set of practices to
organize the feedback process; shepherding and writers’ workshops are two particu-
larly important ones [Coplien 1997].
At the heart of each pattern is a problem-solution pair. Its forces and the discus-
sion of consequences support informed decision making, for instance, about desired
and achieved quality characteristics—but also about the downsides of certain
designs. Alternative solutions are discussed, and pointers to related patterns and
possible implementation technologies complete the picture.
Note that patterns do not aim at providing complete solutions but serve as
sketches to be adopted and tailored for a particular, context-specific API design. In
other words, patterns are soft around their edges; they outline possible solutions but
do not provide blueprints to be copied blindly. How to adopt and realize a pattern to
satisfy project or product requirements remains the responsibility of API designers
and owners.
We have been applying and teaching patterns in industry and academia for a long
time. Some of us have written patterns for programming, architecting, and integrat-
ing distributed application systems and their parts [Voelter 2004; Zimmermann
2009; Pautasso 2016].
We found the pattern concept to be well suited for the usage scenarios stated ear-
lier under “Goals and Scope” and “Target Audience.”
• What is the architectural role played by each API endpoint? How do the end-
point roles and the responsibilities of operations impact service size and
granularity?
• What is an adequate number of representation elements in request and
response messages? How are these elements structured? How can they be
grouped and annotated with supplemental information?
• How can an API provider achieve a certain level of API quality while at the
same time using its resources in a cost-effective way? How can quality trade-
offs be communicated and accounted for?
• How can API professionals deal with life-cycle management concerns such as
support periods and versioning? How can they promote backward compatibil-
ity and communicate unavoidable breaking changes?
1. https://europlop.net/content/conference.
2. We decided not to include big collections of known uses in the book; such information is available
online and in the EuroPLoP conference proceedings from 2016 to 2020. In some of the supplemental
resources, you can find extra implementation hints as well.
xxx Preface
Preface:
Goals and Scope, Target Audience, Patterns, Content Organization, Reading Order
Part 2
Part 1
Chapter 4: Part 3
Pattern Language Introduction
Chapter 1:
API Fundamentals Chapter 10:
Chapters 5 to 9: Real-World
Chapters
Pattern 5 to 9:
Themes Pattern Stories
Chapter 2: Chapters 5 to 9:
Pattern Themes
Lakeside Mutual Chapters
Pattern Themes5 to 9:
Case Study Chapters
Pattern Themes5 to 9:
Pattern Reference Chapter 11:
Conclusion
Chapter 3: API
Decision Narratives
Appendices A to C:
A: Endpoint Identification and Pattern Selection Guides (including Cheat Sheet)
B: Implementation of the Lakeside Mutual Case
C: Microservice Domain-Specific Language (MDSL)
Part 1 introduces the domain of API design conceptually, starting with Chapter 1,
“Application Programming Interface (API) Fundamentals.” Lakeside Mutual, our
case study and primary source of examples, appears for the first time with its business
context, requirements, existing systems, and initial API design in Chapter 2, “Lakeside
Mutual Case Study.” We provide decision models that show how the patterns in our
language relate to each other in Chapter 3, “API Decision Narratives.” Chapter 3 also
provides pattern selection criteria and shows how the featured decisions were made in the
Lakeside Mutual case. These decision models may serve as navigation aids when reading
the book and when applying the patterns in practice.
Preface xxxi
Part 2 is the pattern reference; it starts with Chapter 4, “Pattern Language Intro-
duction,” followed by five chapters full of patterns: Chapter 5, “Define Endpoint
Types and Operations,” Chapter 6, “Design Request and Response Message Rep-
resentations,” Chapter 7, “Refine Message Design for Quality,” Chapter 8,
“Evolve APIs,” and Chapter 9, “Document and Communicate API Contracts.”
Figure P.2 illustrates these chapters and possible reading paths in this part; for instance,
you can learn about basic structure patterns such as Atomic Parameter and Parame-
ter Tree in Chapter 4 and then move on to element stereotypes such as Id Element
and Metadata Element found in Chapter 6.
Define
Responsibility Patterns
(Chapter 5)
Evolution Patterns
Align Refine (Chapter 8)
Endpoint Roles
Foundation Patterns
Quality Patterns
(Chapter 4)
(Chapter 7) Versioning
Operation
Integration Types Responsibilities
(API Direction) Message Granularity Lifecycle
Management
Guarantees
API Visibility
Client-Driven
Design Message Content
Documentation Patterns
Basic Structure Message Structuring (Chapter 9)
Patterns Patterns (Chapter 6) Message Exchange
Optimization
API Description
Element Stereotypes
Billing and
Special-Purpose Governance
Representations
Each pattern description can be seen as a small, specialized article on its own,
usually a few pages long. These discussions are structured identically: First, we intro-
duce when and why to apply the pattern. Then we explain how the pattern works
and give at least one concrete example. Next, we discuss the consequences of apply-
ing the pattern and direct readers to other patterns that become eligible once a par-
ticular one has been applied. The names of our patterns are set in small caps
(example: Processing Resource). This pattern template, introduced in detail in
Chapter 4, was derived from the EuroPLoP conference template [Harrison 2003]. We
refactored it slightly to take review comments and advice into account (thank you
Gregor and Peter!). It puts particular emphasis on quality attributes and their con-
flicts, as our patterns deal with architecturally significant requirements; conse-
quently, trade-offs are required when making API design and evolution decisions.
Part 3 features the application of the patterns in two real-world projects in rather
different domains, e-government and offer/order management in the construction
industry. It also reflects, draws some conclusions, and gives an outlook.
xxxii Preface
Register your copy of Patterns for API Design: Simplifying Integration with Loosely
Coupled Message Exchanges on the InformIT site for convenient access to updates
and/or corrections as they become available. To start the registration process, go to
informit.com/register and log in or create an account. Enter the product ISBN
(9780137670109) and click Submit. Look on the Registered Products tab for an
Access Bonus Content link next to this product, and follow that link to access any
available bonus materials. If you would like to be notified of exclusive offers on new
editions and updates, please check the box to receive email from us.
Acknowledgments
We thank Vaughn Vernon for all his feedback and encouragement during our book pro-
ject. We feel honored to be part of his Addison Wesley Signature Series. Special thanks
also go to Haze Humbert, Menka Mehta, Mary Roth, Karthik Orukaimani, and Sandra
Schroeder from Pearson for their excellent support and to Frank Leymann for providing
the foreword and valuable feedback on our work. Our copy editor, Carol Lallier of Clar-
ity Editing, made this late activity a rewarding, even pleasant experience.
The real-world pattern stories in this book would have not been possible without
the cooperation of development projects. Thus, we’d like to thank Walter Berli and
Werner Möckli from Terravis and Phillip Ghadir and Willem van Kerkhof from innoQ
for their inputs and work on these stories. Nicolas Dipner and Sebnem Kaslack created
the initial versions of the patterns icons in their term and bachelor thesis projects. Toni
Suter implemented large parts of the Lakeside Mutual case study applications. Stefan
Kapferer, developer of Context Mapper, also contributed to the MDSL tools.
We want to thank all the people who provided feedback on the content of this
book. Special thanks go to Andrei Furda, who provided input to the introductory
material and reviewed many of our patterns; Oliver Kopp and Hans-Peter Hoidn,
who applied patterns, provided feedback, and/or organized several informal work-
shops with peers; James Higginbotham and, again, Hans-Peter Hoidn, who reviewed
the book manuscript.
In addition, many colleagues provided helpful feedback, especially the shepherds and
writer’s workshop participants from EuroPLoP 2017, 2018, 2019, and 2020. We thank
the following individuals for their valuable insights: Linus Basig, Luc Bläser, Thomas
Brand, Joseph Corneli, Filipe Correia, Dominic Gabriel, Antonio Gámez Díaz, Reto
Fankhauser, Hugo Sereno Ferreira, Silvan Gehrig, Alex Gfeller, Gregor Hohpe, Stefan
Holtel, Ana Ivanchikj, Stefan Keller, Michael Krisper, Jochen Küster, Fabrizio Lazzaretti,
Giacomo De Liberali, Fabrizio Montesi, Frank Müller, Padmalata Nistala, Philipp Oser,
Ipek Ozkaya, Boris Pokorny, Stefan Richter, Thomas Ronzon, Andreas Sahlbach, Niels
Seidel, Souhaila Serbout, Apitchaka Singjai, Stefan Sobernig, Peter Sommerlad, Markus
Stolze, Davide Taibi, Dominic Ullmann, Martin (Uto869), Uwe van Heesch, Timo Ver-
hoeven, Stijn Vermeeren, Tammo van Lessen, Robert Weiser, Erik Wilde, Erik Wittern,
Eoin Woods, Rebecca Wirfs-Brock, and Veith Zäch. We also would like to thank the stu-
dents of several editions of the HSR/OST lectures “Advanced Patterns and Frameworks”
and “Application Architecture” and of the USI lecture on “Software Architecture.” Their
discussion of our patterns and additional feedback are appreciated.
xxxiii
This page intentionally left blank
About the Authors
Mirko Stocker is a programmer by heart who could not decide whether he liked
frontend or backend development more, so he stayed in the middle and discovered
that APIs hold many interesting challenges as well. He cofounded two startups in the
legal tech sector, one of which he still chairs as managing director. This path has led
him to become a professor of software engineering at the Eastern Switzerland Uni-
versity of Applied Sciences, where he researches and teaches in the areas of program-
ming languages, software architecture, and Web engineering.
xxxv
xxxvi About the Authors
Cesare Pautasso is a full professor at the Software Institute of the USI Faculty of
Informatics, in Lugano, Switzerland, where he leads the Architecture, Design, and
Web Information Systems Engineering research group. He chaired the 25th European
Conference on Pattern Languages of Programs (EuroPLoP 2022). He was lucky to
meet Olaf during a brief stint at the IBM Zurich Research Lab back in 2007, after
receiving his PhD from ETH Zurich in 2004. He has co-authored SOA with REST
(Prentice Hall, 2013) and, self-published the Beautiful APIs series, RESTful Diction-
ary, and Just Send an Email: Anti-patterns for Email-centric Organizations on
LeanPub.
Part 1
The three chapters in Part 1 prepare you to make the best use of Patterns for API
Design. Chapter 1, “Application Programming Interface (API) Fundamentals,” intro-
duces basic API concepts and motivates why remote APIs are important and rather
hard to design well. This chapter sets the stage for the following ones.
Chapter 2, “Lakeside Mutual Case Study,” introduces a fictitious case study from
the insurance domain that supplies running examples for the book. The systems of
Lakeside Mutual feature our patterns in action.
Chapter 3, “API Decision Narratives,” gives an overview of the patterns in the
form of decisions required. (The patterns are then covered in depth in Part 2.) Each
decision answers an API design question; the patterns provide the solution alterna-
tives (options). Examples of decision outcomes from the Lakeside Mutual case are
given as well. The decision model presented in this chapter can help you organize
your API design work and/or serve as a checklist in API design reviews.
1
This page intentionally left blank
Chapter 1
Application Programming
Interface (API) Fundamentals
This chapter first establishes the context of remote APIs. Next, it motivates why APIs
are so important today. It also calls out the main design challenges for APIs, includ-
ing coupling and granularity concerns. Finally, it introduces an API domain model to
establish the terminology and concepts used throughout the book.
3
4 Chapter 1 Application Programming Interface (API) Fundamentals
API contracts express the expectations of the interacting parties. Following basic
information-hiding principles, the implementation is kept secret. Only a minimum
amount of information on how to contact the API and how to consume its services
is revealed. For example, the developer of a software engineering tool that integrates
with GitHub is informed how to create and retrieve issues and which attributes (or
fields) an issue contains. The GitHub API does not unveil the programming lan-
guage, database technology, component structure, or database schema within the
issue management application that serves the public API.
It is worth noting that not all systems and services feature APIs from the start;
APIs may also disappear over time. For example, Twitter opened its Web API to
third-party client developers to increase its popularity; soon, an entire client eco-
system emerged that attracted many users. To monetize its user-generated content,
Twitter later closed down the API and acquired some client applications to continue
maintaining them in-house. We can conclude that API evolution over time has to be
managed.
• The transport and networking protocols TCP/IP along with their socket API,
the backbone of the Internet, were developed in the 1970s. The same holds for
file transfer protocols such as FTP and basic file input/output (from/to shared
drives or mounted network file systems), arguably available in all program-
ming languages past and present.
• Remote Procedure Calls (RPCs), such as the distributed computing envi-
ronment (DCE), and object-oriented request brokers, such as CORBA and
Java RMI, added abstraction and convenience layers in the 1980s and 1990s.
Recently, newer variants of RPC, such as gRPC, became popular.
• Queue-based, message-oriented application integration, such as IBM
MQSeries and Apache ActiveMQ, help to decouple communication parties in
the time dimension. They are about as old as RPCs, with new implementations
6 Chapter 1 Application Programming Interface (API) Fundamentals
and flavors emerging since the 2000s. For instance, major cloud providers offer
their own messaging services today. Cloud tenants can also deploy other mes-
saging middleware to cloud infrastructures; RabbitMQ is a frequent choice in
practice.
• Due to the popularity of the World Wide Web, hypermedia-oriented proto-
cols such as HTTP have risen in the last two decades. To qualify as RESTful
would require respecting all architectural constraints of the Representational
State Transfer (REST) style. While not all HTTP APIs do so, HTTP seems to
dominate the public application integration space at present.
• Data processing pipelines built over continuous data streams, such as those
built with Apache Kafka, have their roots in classical UNIX pipes-and-filters
architectures. They are particularly popular in data analytics scenarios (for
example, analysis of Web traffic and online shopping behavior).
Application A Application B
API Client API Endpoint Provider
Remote API
SDK Message
Representation
Middleware
Local API OS Local API
Platform A Platform B
Network Protocols
(often TCP/IP)
Figure 1.1 Message-based integration and concepts in remote APIs (OS: operating system,
SDK: software development kit)
Remote APIs provide a virtual, abstract connection between the integrated appli-
cation parts. Each remote API is realized by at least three other APIs: a local one both
on the client side and on the provider side plus a remote interface on the next lower
layer of the communication stack. The two local interfaces are provided by operating
system, middleware, or programming language libraries and software development
kits (SDKs); they are consumed by the applications on both the API client and the
API provider sides. These local interfaces expose the networking/transport proto-
col services, such as HTTP over TCP/IP sockets, to application components, subsys-
tems, or entire applications requiring integration.
To reach the common goal of interoperable communication, a shared under-
standing between the communication participants has to be established in an API
contract. When defining API contracts, protocols and endpoints supporting them
are one side of the coin; the exposed data is the other. Request and response mes-
sage representations have to be structured somehow.1 Even file import/exports or
transfers require careful message design; the files contain these messages in that case.
Clipboard-based integration has similar properties. The API contract describes the
1. It depends on the message exchange pattern in use whether a response message is present (our API
domain model, introduced later in this chapter, covers this topic).
8 Chapter 1 Application Programming Interface (API) Fundamentals
shared knowledge about message syntax, structure, and semantics that connects—
but also separates—the two parties.
Our definition of remote API follows from these thoughts:
A remote API is a set of well-documented network endpoints that allow internal and
external application components to provide services to each other. These services help
achieve domain-specific goals, for instance, fully or partially automating business pro-
cesses. They allow clients to activate provider-side processing logic or support data
exchanges and event notifications.
This definition establishes the design space of our book. Note that our book is
on remote APIs; hence, the term API refers to remote APIs from now on—unless we
explicitly say that we mean a local API.
Designing APIs is highly challenging. Many decision drivers, also called forces or
quality attributes, play vital roles in their design. “Decision Drivers in API Design,”
later in this chapter, discusses these desired qualities.
APIs Matter
Let us now visit some business domains and technology areas in which we find many
APIs today.
• Create and manage ad campaigns. Obtain the status of keywords and ads.
Generate keyword estimates. Generate reports about campaign performance.
• Open bank accounts with customer identity verification.
• Manage and deploy applications on virtual machines and track resource
consumption.
• Identify a single person. Find their phone numbers, email addresses, locations,
and demographics.
• Collect, discover, and share your favorite quotes.
From Local Interfaces to Remote APIs 9
In all these examples, API contracts define where and how to call the API, which
data to send, and how received responses look. Some of these domains and services
actually depend on APIs and would not exist without them. Let us now investigate
some of these domains and services in more depth.
10 Chapter 1 Application Programming Interface (API) Fundamentals
Application Application
Frontend Backend
Queue
Tenant Ops Mobile App
APIs Cloud
Database
Business Logic
API
Other Cloud
Storage
Cloud
Compute
API Services
External Services
(Other Cloud, On Premise)
Trait 2, rightsized and modular, directly calls for the introduction of APIs.
Cloud application management (trait 5) also requires APIs, and DevOps tool chains
(trait 7) benefit from them, too.
The cluster management software Kubernetes, for example, has become a pop-
ular choice for running applications and orchestrating the underlying computing
resources both on premises and in the cloud. It addresses the problem of having
to deploy many individual applications and services repeatedly. All these applica-
tion services communicate with each other and with their clients through APIs. The
Kubernetes platform itself also exposes management APIs [Kubernetes 2022] as
well as command-line interfaces. Its operator concept, exposed via API and an SDK
12 Chapter 1 Application Programming Interface (API) Fundamentals
on top of it, promotes extensibility. Application APIs can even be managed with
Kubernetes.
As another example, software-as-a-service providers typically not only provide
customizable, multitenant end-user applications but also open up their applica-
tion functionality to third parties via HTTP. An example is Salesforce, offering data
access and integration in HTTP APIs. At the time of writing, 28 APIs were avail-
able, covering rather diverse domains such as marketing, business-to-consumer com-
merce, and customer data management.
Data consistency and state management challenges are introduced, for example,
when decoupling monolithic, stateful applications into independent, autonomous
microservices [Furda 2018]; single points of failure or cascading failure proliferation
effects have to be avoided. Autonomy and consistency for the whole microservice
architecture cannot be guaranteed at the same time when employing a traditional
backup and disaster recovery strategy [Pardon 2018]. Scaling the architecture to
include a large number of microservices requires a disciplined approach to their life
cycle management, monitoring, and debugging.
Some of these challenges can be overcome with adequate infrastructures. For
example, load balancers introduce (managed) redundancy and circuit breakers
[Nygard 2018a] reduce the risk that failing downstream microservice instances bring
down upstream ones (and, eventually, the entire system). The service APIs still have
to be rightsized and evolved properly over time.
In this book, we are not concerned with microservices infrastructures but with
service rightsizing on the API level (in terms of endpoint granularity and operation/
data coupling). However, infrastructure design is eased when API services have ade-
quate sizes; so indirectly, we are also concerned about infrastructure design.
Wrap Up
All examples, scenarios, and domains we have visited in this section contain and
depend on remote APIs and their contracts, and there are more. If you are up for a
round of buzzword bingo: APIs are an enabling technology for most (if not all) major
trends in recent years—not only mobile/Web and cloud, as mentioned earlier, but
also artificial intelligence and machine learning, the Internet of Things, smart cities,
and smart grids. Even quantum computing in the cloud relies on APIs; see, for exam-
ple, the Quantum Engine API provided by Google Quantum AI.4
4. Bingo!
Decision Drivers in API Design 15
If the API is used in a commercial setting, the success of an API can be assessed
according to business value focusing on the economic sustainability of the service
operating costs versus the revenues generated directly or indirectly from each API
client. Different business models are possible, ranging from freely accessible APIs,
funded by advertisers interested in mining the data willingly (or not willingly?) pro-
vided by users of the applications built on top of the API, to subscription-based APIs
and pay-per-use APIs offered under different pricing plans. For example, Google
Maps used to be a standalone Web application. The Google Maps API appeared
only after users started to reverse engineer how to embed map visualizations in
their own Web sites. Here, an initially closed architecture opened up following user
demand. The initially freely accessible API was later turned into a lucrative pay-per-
use service. OpenStreetMap, the open-source alternative to Google Maps, also pro-
vides several APIs.
A second success factor is visibility. The best API design will fail if its prospective
clients do not know it exists. Public APIs, for instance, may be discovered via links
to provided APIs in company products and product documentation or by advertis-
ing their existence within developer communities. Moreover, API directories such as
ProgrammableWeb and APIs.guru exist. Either way, investments for making the API
known should pay off eventually.
Time to market for APIs can be measured in terms of how long it takes to deploy
new features or bug fixes to an API as well as in terms of how long it takes to
develop a fully functional client for the API. The time to first call is a good indicator
of the quality of the API documentation and the onboarding experience of client
16 Chapter 1 Application Programming Interface (API) Fundamentals
developers. To keep this measure low, the learning effort should be low, too. Another
metric might be the time to first level n ticket—hopefully, it takes a long time for an
API client developer to find a bug that requires level 1, 2, or 3 support to resolve.
Another success measure is the API lifetime. APIs may outlive their original
designers. A successful API usually survives because it keeps attracting clients by
adapting to their changing needs over time. However, a stable API that does not
change for a long time can still be in active use by clients—including those not having
an alternative, such as when fulfilling regulatory compliance requirements via stand-
ardized, slow-moving e-government APIs.
In summary, APIs enable rapid integration of systems and their parts in the short
term and have to support the autonomy and independent evolution of these systems
in the long term. The goal of rapid integration is to decrease the cost of bringing
two systems together; independent evolution has to prevent systems from becoming
so entangled and coupled that they can no longer be separated (or replaced). These
objectives conflict with each other to some extent—which will keep us busy through-
out the book.
These questions, options, and criteria challenge API designers; different choices
are made in different requirements contexts. Our patterns discuss possible answers
and their consequences.
• Client diversity: The wants and needs of API clients differ from one client to
another, and they keep changing. API providers have to decide whether they
want to offer good-enough compromises in a single, unified API or try to sat-
isfy specific, diverging client requirements individually.
• Market dynamics: Competing API providers trying to catch up on each other’s
innovations may cause more change and possibly incompatible evolution strat-
egies than clients are able or willing to accept. Furthermore, clients look for
standardized APIs as a means of preserving their independence from specific
providers, while some providers may be tempted to lock clients in by offering
enticing extensions. Wouldn’t it be nice if Google Maps and OpenStreetMap
APIs implemented the same set of APIs? Client and provider developers might
answer this question differently.
18 Chapter 1 Application Programming Interface (API) Fundamentals
5. How many XML developers and tools are still out there?
Decision Drivers in API Design 19
In summary, API design can make or break software projects, products, and eco-
systems. An API is not just a mere implementation artifact but an integration asset;
APIs have to be architected well due to their dual connector-separator role and typi-
cally long lifetime. While technologies come and go, many of the underlying design
problems for integration designers and solutions to them stay the same.
Related architecturally significant requirements, covered next, change somewhat,
but a common set has stayed relevant for a long time.
6. Think of business processes and corresponding forms to be filled out and approvals required in large
enterprises: typically, many activities and data fields are added with good intentions, but these addi-
tions hardly ever replace existing ones.
Decision Drivers in API Design 21
Developer Experience
The DX metaphor and analogy to user experience (UX) has become quite popular in
recent years. According to Albert Cavalcante’s blog post “What Is DX?” [Cavalcante
2019], the four pillars of a pleasant DX, combining input from UX with software
design principles, are
7. We might be able to train them in some constrained domains such as image recognition, but we cannot
expect them to build a value system and behave morally/ethically as humans (hopefully) do.
22 Chapter 1 Application Programming Interface (API) Fundamentals
While DX receives a lot of attention (rightfully) and can be seen to include main-
tainer experience and consultant/educator/learner experience, do we hear and know
enough about the operator experience?
In conclusion, API success indeed has at least two facets, short-term positivity
and long-term use:
First impressions last. The easier and clearer it is to successfully place the first call to
an API, and to do something meaningful with the responses, the more client developers
will use the API—and enjoy the experience (with regards to function, stability, ease of
use, and clarity). Runtime qualities such as performance, reliability, and manageability
decide whether a positive initial developer experience causes API usage to sustain.
The next and final section in this chapter introduces the API domain model that
serves as our book vocabulary and glossary.
Communication Participants
At an abstract level, two kinds of communication participants (participants, for
short) communicate via an API, the API provider, and the API client. An API client
may use (or consume) any number of API endpoints. The communication is gov-
erned by the API contract, which is exposed by the API provider and consumed by its
clients. This API contract contains information about the available endpoints that
offer the functionality specified by the contract. Figure 1.3 visualizes these basic con-
cepts and relations.
A Domain Model for Remote APIs 23
Communication
uses
Participant
* 1
consumes exposes
* *
API Contract lists API Endpoint Address
1 1..* has
offers 1 1
1 1..*
Figure 1.3 Domain model for API design and evolution: Communication participants, API
contract, API endpoint
Note that the API as a whole is not shown in the figure; an API is a collection of
endpoints with the contracts offered by them. An API endpoint represents the pro-
vider-side end of a communication channel; an API contains at least one such end-
point. Each API endpoint has a unique address such as a Uniform Resource Locator
(URL), commonly used on the World Wide Web, RESTful HTTP, and HTTP-based
SOAP. In the client role, a communication participant accesses an API via such an
endpoint. A communication participant may play both the client role and the pro-
vider role. In that case, a communication participant offers certain services as an API
provider but also consumes services offered by other APIs in its implementation.8
In service-oriented architecture terminology, the term service consumer is a
synonym for API client; the API provider is called service provider [Zimmermann
2009]. In HTTP, an API endpoint corresponds to a set of related resources. A home
resource with a prepublished URI is an entry-level URL to locate and access one or
more related resources.
8. The client-side of a communication channel also requires a network endpoint, which is not depicted
here due to our focus on APIs rather than communication channels or networking.
24 Chapter 1 Application Programming Interface (API) Fundamentals
9. In OpenAPI specifications, operations are identified by the HTTP method and its URI path; there also
is an additional property, operationId [OpenAPI 2022].
A Domain Model for Remote APIs 25
Request/Reply
Command
Message
One-Way composed of
Exchange
*
Conversation Message Document
comprises Message
- header
* * - body
Event
Notification
Event Message
From Enterprise
Request-
Integration Patterns
Multiple Replies
(Callbacks)
Many other kinds of conversations exist, including more complex ones like
publish-subscribe mechanisms. Basic conversations can be composed into larger
end-to-end conversations scenarios involving message exchanges between multi-
ple API clients and providers up to managed business processes that run for days,
months, or years. [Pautasso 2016; Hohpe 2017]. Such advanced conversations can
commonly be found in software ecosystems, enterprise applications, and other API
usage scenarios, but they are not our main focus in this book.
contains from
Message address Address API Endpoint
1 0..1 has
- header
- body 1 1
1 contains to
address 0..1
1
has
1..*
Representation Representation
assembles Element
+ serialize() (Parameter)
+ deserialize() * *
API Contract
Figure 1.7 shows that all endpoint operations are specified in the API contract (which we
introduced in Figure 1.3). Such a contract may detail all possible conversations and mes-
sages down to the protocol-level message representations (parameters, bodies) and
network addresses. API contracts are necessary to realize any interoperable, testable, and
evolvable runtime communication because API clients and API providers must agree on
the shared knowledge specified in the contract in order to be able to communicate.
10. A DTR can be seen as a wire-level equivalent of a program-level pattern data transfer object (DTO)
[Fowler 2002; Daigneau 2011].
A Domain Model for Remote APIs 27
In reality, this agreement can be highly asymmetrical because many APIs (espe-
cially public APIs) are offered as-is by the API provider. API clients can use it under
those conditions or not at all; no negotiation or formal agreement on a contract
between the participants takes place in such cases. This might be different if the API
client pays for the service. In that case, the API contract might be the result of an
actual negotiation and be accompanied by (or even part of) a legal contract. An API
contract can either be documented minimally or be part of a more comprehensive
API Description and/or Service Level Agreement (two of our patterns).
Communication
Participant uses
agrees
on
*
API Contract
1 1
describes offers
* 1..*
+ ID: String
Figure 1.7 Domain model: An API contract describes operations (that are invoked in
conversations comprising messages)
driver for a decision for or against a pattern. For instance, the parameter structure of
each occurrence of a message has to be decided. Chapter 3, “API Decision Narra-
tives,” picks up these thoughts and guides us through the decision making about all
domain model elements and patterns.
Finally, the Microservices Domain-Specific Language (MDSL) that we use to
model some examples is designed according to this domain model. See Appendix C,
“Microservice Domain-Specific Language (MDSL),” for reference information.
Summary
In this chapter, we discussed the following:
• What APIs are and why they are important—and challenging—to design well.
• Desired qualities in API design, including coupling and granularity considera-
tions and elements of a positive developer experience (DX).
• The API domain terminology and concepts we use in this book.
APIs, both local APIs inside modular programs and remote APIs connecting oper-
ating system processes and distributed systems, have been around for a long time.
Message-based protocols such as RESTful HTTP, gRPC, and GraphQL dominate
the remote API realm at present. Remote APIs provide the means to access server-side
resources via protocols for application integration. They play the role of an impor-
tant intermediary, which connects multiple systems while keeping them as separate
as possible to minimize the impact of future changes. An API and its implementa-
tions may even remain under separate control and ownership. Any API, whether
local or remote, should address an actual client information or integration need and
be purposeful.
A real-world metaphor would be to see the API as an entrance door and hall of
a building, for instance, the lobby welcoming visitors to a skyscraper, routing them
to the right elevator but also checking whether they are allowed to enter through the
main door. First impressions last when entering a place for the first time—in real
life between humans, when humans use software, or when API clients use APIs. An
API portal, then, serves as a set of “business cards” (or building map) of the applica-
tion behind the API, introducing services to developers potentially interested in using
them to build their own applications. Both business cards and entrance hall influence
the visitor experience (in this case, DX).
Getting local APIs right is one thing. For remote APIs, the fallacies of distributed
computing come into play. Networks cannot be assumed to be reliable, for example,
Summary 29
Why is it hard (and interesting) to get API design and evolution right?
• APIs are supposed to live long; API success has a short-term and a long-term
perspective.
• APIs require different and diverse parties to reach agreements regarding
exposed functionality and related qualities.
• The granularity of APIs is determined by the number of endpoints and oper-
ations exposed as well as by the data contracts of the request and response
messages of these operations. An important decision point concerns choosing
between a few rich operations and many narrow ones.
• Coupling control is required. Zero coupling means being disconnected; the
more API client and API provider (have to) know about each other, the tighter
they are coupled, and the harder it becomes to evolve them independently.
• While API technologies come and go, the fundamental concepts of API design
and the related architectural decisions with their options and criteria stay.
30 Chapter 1 Application Programming Interface (API) Fundamentals
Our focus in this book is on remote APIs connecting systems and their parts. API
providers expose API endpoints, which have operations; operations are called via
message exchanges. The messages in these exchanges form conversations; they con-
tain flat or structured message representation elements. We defined these concepts in
a domain model for API design and evolution. Bringing these concepts to life so that
the resulting APIs meet the wants and needs of their clients with certain qualities is
our task at hand.
What’s up next? Chapter 2, “Lakeside Mutual Case Study,” introduces a larger,
fictitious yet realistic example of an API and service design. Chapter 3 picks up the
design challenges and requirements from this section in the form of decision drivers.
The forces and their resolution in the patterns in Part 2, the pattern reference, also
elaborate on these success factors and quality properties.
Chapter 2
This chapter introduces the Lakeside Mutual case study that serves as our example
scenario running through the book. To motivate the need for APIs in this scenario
and to be able to justify API design decisions in later chapters, sample systems and
the requirements they face are presented, along with an initial API design serving as
an outline and preview.
Lakeside Mutual is a fictitious insurance company that provides several digital
services to its customers, partners, and employees. Its company backend consists of
several enterprise applications for customer, policy, and risk management; the appli-
cation frontends serve multiple channels from smartphone apps for prospective and
insured clients to rich client applications for company staff members and third-party
sales agents.
31
32 Chapter 2 Lakeside Mutual Case Study
Let us inspect these artifacts now. They provide valuable input to the API design.
schedule a home visit. The enterprise applications use domain-driven design (DDD)
[Evans 2003; Vernon 2013] to structure their domain (business) logic. Figure 2.1
shows the three main aggregates Customer, InsuranceQuoteRequest, and Policy.1
«Aggregate»
InsuranceQuoteRequest
«Aggregate» «Aggregate»
Policy Customer
insures
We now zoom into these three aggregates to explore additional DDD concepts.
Insurance quote requests come from existing or prospective customers. They inquire
about offers for new insurance policies (such as health care or car insurance). Offers
and policies know about the customers who (will) pay for them and who may issue
claims in the future.
Figure 2.2 shows the components of the InsuranceQuoteRequest aggregate, which
is an example of short-lived operational data. It comprises several entities with an
identity and life cycle and immutable value objects. An entity with a unique role is the
InsuranceQuoteRequest aggregate root. It serves as an entry point into the aggregate
and holds the components of the aggregate together. We can also see some outgoing
references to other aggregates, pointing at the respective aggregate root entities. For
example, an InsuranceQuoteRequest references a customer’s existing policies that
the customer now wishes to change. The request also includes CustomerInfo, which
refers to one or more addresses, because a policy might pertain to several persons
(and persons might have multiple residences too). For example, health insurance for
children can be part of a parent’s policy.
1. Aggregates are clusters of domain objects loaded and stored together, enforcing the related business
rules.
34 Chapter 2 Lakeside Mutual Case Study
«Aggregate»
InsuranceQuoteRequest
- id: long
- date: Date
customer
insuranceQuote
«Aggregate»
Customer
«entity» «entity»
InsuranceQuote CustomerInfo
Details of the Policy aggregate are shown in Figure 2.3. A policy deals primarily
with value objects such as MoneyAmounts, types of policies, and date periods. Each
policy also has an identifier (PolicyId) used to reference the aggregate from the out-
side. On the right, we can see the reference to the Customer aggregate.
«Aggregate»
Policy
- creationDate: Date
deductible policyLimit
policyType insurancePremium policyPeriod insuringAgreement
agreementItems
«Value Object»
InsuringAgreementItem
In Figure 2.4, we finally arrive at the Customer aggregate that holds the usual
contact information and current and past addresses. Like policies, customers can be
identified uniquely by their CustomerId.
customer customer
«Aggregate»
Customer
«Aggregate Root»
Customer
id customerProfile
- streetAddress: String
- postalCode: String
moveHistory - city: String
Architecture Overview
Now that we know about business context and requirements, let us investigate the
existing systems at Lakeside Mutual and their architectures.
System Context
Figure 2.5 shows the current system context. Existing customers (not shown in the
figure) should be able to use the Customer Self-Service frontend to update their con-
tact information. This service retrieves the master data from the Customer Core
36 Chapter 2 Lakeside Mutual Case Study
Customer Core
U OHS
U
U
Customer/Supplier
D CF
D
U U
Customer/Supplier
Customer/Supplier
D D
D
Customer Self-Service
Figure 2.5 Context map for Lakeside Mutual (solid lines: existing relations, dashed line:
new interface)
The four applications shown as Bounded Contexts in the figure are easy to trace
back to the analysis-level domain model.3 The Customer Self-Service context cur-
rently interacts only with Policy Management and Customer Core. To implement
the new self-service capabilities, a new relationship to the Customer Management
context will be added, which the dashed line in Figure 2.5 indicates. In the next sec-
tion, we look at the software architecture that implements these bounded contexts.
Application Architecture
Refining the system context from Figure 2.5, Figure 2.6 shows an overview of the
core components. These components are the building blocks for the services Lake-
side Mutual provides to its customers and its employees. The Bounded Contexts
from Figure 2.5 have led to the introduction of respective frontend applications and
2. Note that Customer/Supplier, Upstream (U), Downstream (D), Open Host Service (OHS), and Conform-
ist (CF) are context relationships from DDD that call for API design and development [Vernon 2013].
3. The DDD pattern Bounded Context denotes a model boundary; it is an abstraction and generalization
of teams, systems, and system parts (such as application frontends and backends).
Architecture Overview 37
«Spring Boot»
Customer Core
The frontend strategy is to use rich Web clients; hence, single-page applications
(SPAs) are implemented in JavaScript. Due to a strategic decision made on the com-
pany level several years ago, most backends are realized in Java, leveraging Spring
Boot dependency injection containers to promote flexibility and maintainability. As
a widespread and mature open-source messaging system, Apache ActiveMQ is used
to integrate customer self-service and policy management.
38 Chapter 2 Lakeside Mutual Case Study
• Customer Core: The Customer Core manages the personal data about the
individual customers (for instance, name, email, current address, etc.). It pro-
vides this data to the other components through an HTTP resource API.
• Customer Self-Service Backend: The Customer Self-Service backend provides
an HTTP resource API for the Customer Self-Service frontend. In addition, it
connects to an ActiveMQ broker provided by the Policy Management backend
to process insurance quote requests.
• Customer Self-Service Frontend: The Customer Self-Service frontend is a React
application that allows users to register themselves, view their current insurance
policy, and in the future, change their address (our exemplary user story).
• Customer Management Backend: The Customer Management backend is a
Spring Boot application that exposes an HTTP resource API for the Customer
Management frontend and the Customer Self-Service frontend. In addition,
Web Sockets are used to implement the chat feature to deliver chat messages in
real time between the call center agent using the Customer Management front-
end and the customer logged into the Customer Self-Service Frontend.
• Customer Management Frontend: The Customer Management frontend is a
React application that allows customer-service operators to interact with cus-
tomers and help them resolve issues related to Lakeside Mutual’s insurance
products.
• Policy Management Backend: The Policy Management backend is a Spring
Boot application that provides an HTTP resource API for the Customer Self-
Service frontend and the Policy Management frontend.
• Policy Management Frontend: The Policy Management frontend is a Java
Script application built with vue.js that allows Lakeside Mutual employees to
view and manage the insurance policies of individual customers.
How can patterns help the API designers at Lakeside Mutual when dealing with
these tasks? This question will be answered in the following (and the remainder of
the book). Appendix B, “Implementation of the Lakeside Mutual Case,” collects
some of the API implementation artifacts for the case.
"postalCode": D<string>,
"city": D<string>
}
4. Originally, YAML stood for “Yet Another Markup Language.” However, the name was later changed
to “YAML Ain’t Markup Language” to distinguish it as a data serialization language, not a true
markup language.
Summary 41
At the top level, we can see the API description, two data type definitions, and an
endpoint featuring a single operation. The <<API_Key>> stereotype, SOLUTION_
INTERNAL_API, FRONTEND_INTEGRATION, INFORMATION_HOLDER_RESOURCE,
and STATE_TRANSITION_OPERATION markers (and several others) all refer to pat-
terns. In the next part of the book, these are explained in detail.
Summary
In this chapter, we introduced Lakeside Mutual, a fictitious case study that supplies
us with running examples throughout the remainder of the book. Lakeside Mutual is
an insurance company that implemented its core business capabilities for customer,
contract, and risk management as a set of microservices with corresponding applica-
tion frontends:
We elaborate on this initial API design in Chapter 3 and in Part 2 of the book,
revisiting the patterns and the rationale for their application in the business and
architectural context of the API design of the customer self-service API.
Some excerpts of the API implementation can be found in Appendix B. A com-
plete implementation of the scenario is available at GitHub.5
5. https://github.com/Microservice-API-Patterns/LakesideMutual.
This page intentionally left blank
Chapter 3
API endpoint, operation, and message design is multifaceted and therefore not easy.
Requirements often conflict with each other, requiring balancing acts. Many archi-
tectural decisions and implementation choices have to be made, with numerous solu-
tion options available. The key to the success of an API is getting these decisions
right. Sometimes the required choices are not known to developers, or developers
know only a subset of the available options. Also, not all criteria may be obvious; for
example, some quality attributes (such as performance and security) are more obvi-
ous than others (such as sustainability).
In this chapter, we identify pattern selection decisions by topical categories. The
chapter walks through an API design iteration, starting with API scoping and then
moving on to architectural decisions about endpoint roles and operations respon-
sibilities. Decisions about quality-related design refinements and API evolution are
covered as well. We call out the decisions required along with the most prevalent
options (as covered by patterns from Part 2) and criteria for pattern selection that we
have seen in practice.
43
44 Chapter 3 API Decision Narratives
alternatives. These alternative options are provided by our patterns, which are cov-
ered in depth in Part 2 of the book.
To identify decisions required, we use the following format:
Sample decision outcome. We also present examples of decisions from the Lake-
side Mutual case introduced in Chapter 2, “Lakeside Mutual Case Study.” We use
the following architectural decision record (ADR) format:
In the context of [feature or component],
wanting to/facing the need for [requirement or quality goal],
we decided to [option chosen]
and neglected [alternatives]
to achieve [benefit],
accepting that [negative consequences].
1. See https://ozimmer.ch/practices/2020/04/27/ArchitectureDecisionMaking.html.
Foundational API Decisions and Patterns 45
Each why-statement is set in italics so that it is clearly distinguished from the con-
ceptual content of this chapter (the decision points, options, and criteria, that is).
The “neglected” part of the why-statement is optional, and not used in this example.
In the remainder of the chapter, we cover the following decision topics:
• “Foundational API Decisions and Patterns” features API visibility, API integra-
tion types, and documentation of the API.
• “Decisions about API Roles and Responsibilities” discusses the architectural
role of an endpoint, refining information holder roles, and defining operation
responsibilities.
• “Selecting Message Representation Patterns” covers the choice between flat
and nested structures of representation elements and introduces element
stereotypes.
• “Governing API Quality” is multifaceted: identification and authentication of
the API client, metering and charging for API consumption, preventing API cli-
ents from excessive API usage, explicit specification of quality objectives and
penalties, communication of errors, and external context representation.
• “Deciding for API Quality Improvements” deals with pagination, other
means of avoiding unnecessary data transfer, and handling referenced data in
messages.
• “Decisions about API Evolution” has two parts: versioning and compatibility
management and strategies for commissioning and decommissioning.
• Where should the API be accessible from, or how visible is the API?
• Which integration types should be supported by the API?
• Should the API be documented? If so, how should it be documented?
«Category»
Foundations
«Decision»
API Visibility
«Optional Next» «Optional Next»
document visible combine integration type
aspects of the API with selected visibility
contract option
The first decision in this category is on API visibility. In different kinds of APIs,
the API clients that are supposed to use the API might be vastly different, ranging
from a large number of API clients residing in different organizations and locations
to a few well-known API clients within a single organization and/or the same soft-
ware system.
In addition, it has to be decided how the organization of a system in physical tiers
is related to APIs, leading to different possible integration types. A frontend that is
responsible for displaying and controlling an end user interface might be physically
separated from its backends that are in charge of data processing and storage. Such
backends might be split and distributed into several systems and/or subsystems, for
instance, in service-oriented architectures. In both cases, frontend and backend, API-
based integration is possible.
Finally, decisions about API documentation are required. When a service pro-
vider has decided to expose one or more API endpoints, clients must be able to find
out where and how API operations can be called. This includes technical API access
information, such as API endpoint locations or parameters in message representa-
tions, as well as documentation of operation behavior, including pre- and postcondi-
tions, and related quality-of-service guarantees.
API Visibility
You may want to provide a part of an application with a remote API exposing one or
more API endpoints. In such a scenario, an early decision on each API pertains to its
visibility. From a technical viewpoint, this visibility of an API is determined by the
deployment location and its network connections (for instance, the Internet, an
extranet, a company-internal network, or even a single data center). From an organi-
zational viewpoint, the end users served by the API clients influence the required level
of visibility.
This decision is not primarily technical but a managerial or organizational one.
It is often related to budgets and funding considerations. Sometimes the API devel-
opment, operations, and maintenance are funded by a single project or product; in
other cases, several organizations (or units within one) contribute to the API funding.
The decision has important impacts on many technical aspects, however. Com-
pare, for instance, an open, public API exposed on the Internet used by an arbitrary
number of partially unknown API clients to a solution-internal API used by a small
and stable number of other systems and/or subsystems of an organization. The pos-
sible workload that the open, public API has to tolerate might be rather high and
contain numerous peaks; the workload of a solution-internal API with a few well-
known API clients often is significantly lower. As a consequence, the performance
and scalability requirements for the two kinds of API visibility can be very different.
48 Chapter 3 API Decision Narratives
Figure 3.2 illustrates the three decision options for this decision, described as
patterns.
«Decision»
API Visibility
Specifically for Public APIs, it is important to consider the target audience size,
location, and diversity. The wants and needs of the target audience, possible devel-
opment and middleware platforms they use, and other such considerations can help
determine whether and how an API should be publicly offered. For example, the
trend toward single-page applications that access APIs through the browser (in con-
trast to dynamic Web sites rendered on the server) has led to an increase in APIs that
are accessible over the Internet.
Public APIs with high visibility often have to cope with continuously high work-
loads and/or peak loads. This can increase the complexity and require high maturity
of backend systems and data stores. Possible loads the API has to take are dependent
on the target audience size. The location of the target audience determines the level
of Internet access and bandwidth required.
More visible APIs might have higher security demands than less visible ones. The
use of API Keys or, alternatively, authentication protocols usually indicates the dif-
ference between a Public API in general and its Open API variant: a truly open API
is a Public API without an API Key or other authentication means. Both API Keys
and authentication protocols can also be used in all other options of this decision,
of course.
The costs of API development, operations, and maintenance have to be covered.
Usually, an API must have a business model for generating funds. For Public APIs,
paid subscriptions and per-call payments (see Pricing Plan pattern) are common
options. Another option is cross-funding, for instance, via advertising. Such consid-
erations must go along with budget considerations. While it might be easy to fund
the initial development of the first version of an API, its operations, maintenance,
and evolution might be harder to fund in the long run, especially for a successful
Public API with a large number of clients.
An alternative decision option with more limited visibility is Community API.
As for a Public API, the API development, operations, and maintenance of Com-
munity APIs must be funded. Thus, budgets play an equally important role, but
here the specifics of the community and solutions they require determine how they
are covered. In a community of product users, for example, license fees might cover
the budget. A government or nonprofit organization might fund APIs for specific,
restricted user groups to achieve certain community-specific goals. An essential dif-
ference to Solution-Internal APIs (explained shortly) is that it is often not a single
project or product budget that pays for the API. The interests of those who pay for
the API can be diverse.
More variants of the pattern exist, often observed in company contexts. An
Enterprise API is an API that is available within a company-internal network only. A
Product API ships with purchased software (or open-source software). Finally, Ser-
vice APIs exposed by cloud providers and the application services hosted in cloud
environments also qualify as variants of Community API if access to them is limited
and secured.
The target audience size, location, and technical preferences play a role, too (often
even related to the budget considerations, as members of the community might pay
for the API). These community characteristics might be significantly more challeng-
ing and more diverse than those of individual teams or the public. In contrast to a
Public API, where the API development organization often can set standards easily
because the users are politically relatively weak, stakeholder concerns in bounded
communities are often diverse and demanding. For example, the concerns of roles
such as application owner, DevOps staff, IT security officer, and so on, might differ
and conflict with each other. These considerations might also make API life-cycle
management more demanding. For example, a paying customer of a Community
API might have rather strong demands that an API version remains in operation.
Finally, the decision option with the most limited visibility is Solution-Internal
API.
As for the prior two patterns, the budget must be considered to fund the develop-
ment, operations, and maintenance of the Solution-Internal API. This is usually
less problematic for Solution-Internal APIs than for the two other API visibility
types (which are more exposed) because a single project or product budget typically
covers the costs of the API. This, in turn, means that the project can also decide
about life-cycle considerations and supported target audience size, location, and
technical preferences. Naturally, the significance of these concerns depends on the
project goals. For example, consider an internal API developed to invoice product
purchases in an online shop. It can be expected that the products and their billing
requirements are known to the API development team; they change over time. If the
team rolls out a new API version, it can notify the dependent teams, working on the
same shop application, about the change.
Other technical concerns raised previously have a similar character. Workloads
are typically better known than in Public APIs unless the Solution-Internal API
receives its calls from a Public API. For example, in the billing scenario, if all com-
pany products themselves are offered via Public APIs, then the Solution-Internal
API for billing has to cope with the loads coming from those Public APIs. Likewise,
the complexity and maturity of backend systems and data stores, as well as security
demands, have to fulfill only solution-internal demands and can follow best practices
used in the organization that offers them.
Note that sometimes Solution-Internal APIs evolve into Community APIs (or
even Public APIs). Such graduation should not just happen as a form of scope creep
but should be decided and planned consciously. Some API design decisions, such as
those about API security, might have to be revisited when such graduation happens.
Also note that API visibility includes message and data structure visibility. API
client and provider require a shared understanding of the data structures exchanged.
In domain-driven design terms, these data structures are part of the Published Lan-
guage [Evans 2003]. A rich Published Language has the potential to contribute to a
positive developer experience; however, it also introduces coupling inherently.
Sample decision outcome. How did the case study team at Lakeside Mutual
decide, and why?
In the context of the customer self-service channel,
facing the need to serve external users such as existing customers,
the API designers at Lakeside Mutual decided to evolve their SOLUTION-INTERNAL
API into a COMMUNITY API, neglecting PUBLIC API,
to be able to address the wants and needs of a known user population and predict
the API workload,
52 Chapter 3 API Decision Narratives
Figure 3.3 shows the two decision options, Frontend Integration (or vertical
integration) and Backend Integration (or horizontal integration).2
«Decision»
API Integration
Types
«Option» «Option»
integrate two or integrate frontend
more backends and backend
horizontally vertically
«Pattern» «Pattern»
Backend Frontend
Integration Integration
2. The notion of horizontal versus vertical integration originates from the common visualization of dis-
tributed systems (and their layers and tiers) that places frontends at the top of diagrams and backends
at the bottom.
Foundational API Decisions and Patterns 53
Both integration types can be combined with any of the visibility patterns
discussed earlier.
For many backend integrations, runtime qualities such as performance and scal-
ability have to be taken into account. For instance, some backends may in turn serve
multiple frontends, or large amounts of data might have to be transferred between
backends. Security might be an important consideration when backend integra-
tions across organizational boundaries are required. Similarly, interoperability is an
important force in some backend integration scenarios. For instance, application
owners and system integrators of the involved systems might not know each other.
For integration tasks, Backend Integration in particular, the development
budget might also be important to consider. As an example, the cost allocations of
Solution-Internal APIs and Community APIs may not be clear, and only limited
budgets can be spent on integration tasks. Integration of systems means that the
development cultures and company politics of the systems to be integrated might
clash or be incompatible.
For both patterns of this decision, Frontend Integration and Backend Inte-
gration, links to the decision options of the API visibility decision exist, such as the
following:
Sample decision outcome. Which Lakeside Mutual API design arose when going
through this decision?
In the context of the customer self-service channel,
facing the need to supply external users with correct data through a user interface,
the Frontend Integration pattern was chosen (and Backend Integration
neglected)
Foundational API Decisions and Patterns 55
to achieve high data quality and productivity gains when customers serve
themselves,
accepting that the external interface has to be secured properly.
HTTPS and the API Key pattern featured in a later decision are two options to
deal with the “accepting that” consequence stated in the sample decision outcome.
«Decision»
Documentation of
the API
«Option» «Option»
do not document the API provide a dedicated API
description for its
documentation
«Do Nothing»
No API «Pattern»
Description API Description «Pattern»
Interface
Description
The essential API-related pattern for this decision is API Description. A small or
simple project, or prototype projects that are likely to change significantly in the
near future, might choose not to apply this pattern and thus select the “no API
Description” option.
Decision: Documentation of the API
Should the API be documented? If so, how should it be documented?
56 Chapter 3 API Decision Narratives
An API Description contains the functional API contract that defines request
and response message structures, error reporting, and other relevant parts of the
technical knowledge to be shared between API provider and client. In addition to
this syntactical interface description, it contains quality management policies as well
as semantic specifications and organizational information. The API contract part is
essentially a special case or variant of the “Interface Description” pattern [Voelter
2004], with the purpose of describing an API. For example, OpenAPI Specification
(formerly known as Swagger), API Blueprint [API Blueprint 2022], Web Application
Description Language (WADL), and Web Services Description Language (WSDL)
are languages for specifying interfaces following the Interface Description pattern
that can be used to describe the technical part of the API Description, the API con-
tracts. Alternatively, more informal descriptions of the API contracts are possible,
too, for example, in textual form on a Web site. Both options, description language
and informal specification, can be combined. MDSL is an example of a machine-
readable language that supports the pattern (see Appendix C, “Microservice
Domain-Specific Language (MDSL)”).
The other parts mentioned in the pattern solution (quality management policies,
semantic specifications and organizational information, invocation sequences, pre-
and postconditions, invariants, and so on) are often described informally in practice.
For many of those, formal languages also exist, for example, to define pre- and post-
conditions and invariants [Meyer 1997] or invocation sequences [Pautasso 2016].
A key aspect of the pattern is that an API Description helps to enable interoper-
ability because it provides a common, programming-language-independent descrip-
tion of the API. In addition, it helps to support information hiding. Providers should
not unveil details about the implementation of the API that clients do not require.
At the same time, clients should not have to guess how to correctly invoke the API.
That is, API designers should care for the consumability and understandability of
Decisions about API Roles and Responsibilities 57
the API. A clear and precise API Description is essential to reach this goal. The API
Description can help to strike a balance between consumability, understandability,
and information hiding.
Independence of API implementation details helps ensure loose coupling of API
clients and providers. Both loose coupling and information hiding are essential to
enable extensibility and evolvability of the API. If clients are not highly dependent
on API implementation details, it is usually easy to change and evolve the API.
In Part 2, the visibility and integration patterns presented in this section appear in
Chapter 4, “Pattern Language Introduction.” API Description is featured in Chap-
ter 9, “Document and Communicate API Contracts.”
The drivers for API introduction and requirements for API design are diverse. As
a consequence, the roles that APIs play in applications and service ecosystems dif-
fer widely. Sometimes, an API client wants to inform the provider about an incident
or hand over some data; sometimes, a client requests provider-side data to continue
client-side processing. Sometimes, the provider has to perform a lot of complex
processing to satisfy the information needs of the client; sometimes, it can simply
return a data element that already exists as part of its application state. Some of the
provider-side processing, whether simple or complex, may change the provider-side
state, some might leave it untouched.
58 Chapter 3 API Decision Narratives
Once the role of an endpoint has been defined (action- or data-oriented), more
fine-grained decisions on the responsibilities of the endpoint operations are due.
Operations can solely compute results, only read state, create new state without
reading it, or realize a state transition. Clearly defining these responsibilities, for
instance, in an API Description, can help developers to better design and choose
deployment options for an API endpoint. For example, if only stateless computa-
tions and data reading are performed on an endpoint, their results can be cached and
the corresponding implementation can be replicated to scale out more easily.
As illustrated in the category overview in Figure 3.5, the responsibility category
contains two decisions. Usually, an (at least initial) architectural role decision is made
during endpoint identification, and then operation responsibilities are designed.
Note that architectural roles have to be decided for each endpoint (or resource),
whereas operation responsibilities should be assigned to each API operation.
«Category»
Responsibility
«Decision» «Decision»
Architectural Responsibility
Role of an API of an API
Endpoint «Next» Operation
Two main options can be chosen in this decision, illustrated in Figure 3.6.
«Category»
Responsibility
«Decision»
Architectural
Role of an API
Endpoint
«Option»
«Option»
a resource whose primary
a resource whose primary function is storage and
function is to process retrieval of data or metadata
incoming commands
«Pattern» «Pattern»
Processing Information
Resource Holder Resource
The basic decision between these two types of resources is relatively easy, as it is
based on the functionalities required by clients. However, there is much freedom to
determine which functions are offered on which resources and how to decompose
the API well. For instance, API designers have to consider contract expressiveness
and service granularity: simple interactions give the client good control and make
processing efficient, but action-oriented capabilities can promote qualities such as
consistency, compatibility, and evolvability. These design choices can be positive or
negative for the learnability and manageability of the API. Also, semantic interop-
erability (including a joined understanding of the meaning of the data exchanged)
must be ensured. If not done well, the chosen endpoint-operation layout can have a
negative impact on response time and lead to chatty APIs.
Decisions about API Roles and Responsibilities 61
A truly stateless Processing Resource can be hard to achieve in reality. API secu-
rity and request/response data privacy can lead to the need for maintaining state, for
example, when a full audit log of all API invocations and resulting server-side pro-
cessing has to be maintained.
The underlying impact on coupling should be considered, particularly for state-
ful resources. Highly data-centric approaches tend to lead to create, read, update,
delete (CRUD) APIs, which can negatively affect coupling. This is discussed later
in more detail for the different kinds of information holder roles. The structure of
some backends could lead to highly coupled APIs when followed as-is; however, API
designers are free to design the API as an additional layer specifically to support the
interactions between the API and its clients. Here, various quality attribute conflicts
and trade-offs specific for API design but also in relation to backend services are to
be considered, such as concurrency, consistency, data quality and integrity, recover-
ability, availability, and mutability (or immutability). Also, such decisions are often
dependent on compliance with architectural design principles such as loose coupling
[Fehling 2014], logical and physical data independence, or microservices tenets such
as independent deployability [Lewis 2014].
Sample decision outcome. How did our case study team resolve the forces of
concern?
In the context of the customer self-service channel at Lakeside Mutual,
facing the need to empower clients to update their contact information easily,
the integration architects at Lakeside Mutual decided to introduce a data-ori-
ented Information Holder and not an activity-oriented Processing Resource
to provide expressive, easy-to-understand create, read, update, and delete
functionality,
accepting that the exposure of contact information couples the self-service chan-
nel to the customer management backend to some extent.
Unlike operational data, master data is long-living and frequently referenced but
still mutable. A Master Data Holder stores such data. Here, master data quality is
often a central decision driver, including master data consistency and its protection,
for example, from attacks and data breaches. Very often, there are external depend-
encies such as data ownership by different organizational units that must be consid-
ered in the design of Master Data Holder resources as well.
For both Operational Data Holders and Master Data Holder, a simple
design is a CRUD resource for each identified interface element that exposes opera-
tional or master data. Use of the words “create, read, update, and delete” in the
preceding pattern sketches should not indicate that such designs are the intended
or only possible solution for realizing the patterns. Such designs quickly lead to
chatty APIs with bad performance and scalability properties. They can also lead to
unwanted coupling and complexity. Beware of such API designs! Instead, we recom-
mend an incremental approach during resource identification. It aims to first iden-
tify well-scoped interface elements such as Aggregate roots in domain-driven design
(DDD), business capabilities, or business processes. Even larger formations such as
Bounded Contexts may serve as starting points. In infrequent cases, domain Enti-
ties can also be considered to supply endpoint candidates. For a deeper discussion
on the relation of APIs and DDD, see [Singjai 2021a, 2021b, 2021c]. This approach
leads to Operational Data Holder and Master Data Holder designs that are
semantically richer. In DDD terms, on the domain model side, we aim for a rich and
deep domain model instead of an “anemic domain model” [Fowler 2003]; this model
should be reflected, but not necessarily mirrored in the API design.
For some data, also long-living, we know that clients do not want to or should not
be allowed to modify it. Such reference data should be offered via a Reference Data
Holder. Caching of this data is possible, which leads to high performance. If caching is
used, consistency versus performance trade-offs might have to be made. Since reference
data rarely changes if at all, there is a temptation to simply hardcode it within the API
clients or retrieve it once and then store a copy locally. Such designs violate the do not
repeat yourself (DRY) principle and work well only in the short run.
As a supporting role, there is the option to design Link Lookup Resources. They
are resources whose primary function is supporting clients that follow or derefer-
ence links to other resources. Links are a primary means to improve coupling and
Decisions about API Roles and Responsibilities 65
cohesion between API consumers and providers, but there is also the coupling to the
Link Lookup Resource to be considered. Links can also help to reduce message sizes
by placing a link in the message instead of the content, as in the Embedded Entity
pattern. But if clients need all or part of the information, this practice increases the
required number of calls. Both placing links in messages and including content in an
Embedded Entity influence the overall resource use. For links to work well, dynamic
endpoint references that can change at runtime should ideally be established. Link
Lookup Resources increase the number of endpoints in an API and can lead to
higher API complexity; the severity of consequence depends on how centralized or
decentralized Link Lookup Resources are. Finally, the consistency issue of dealing
with broken links has to be considered: a link lookup provides the option to deal
with the problem, whereas a broken link without a lookup usually immediately leads
to an exception (i.e., a “resource not found” error).
Sample decision outcome. The API designers at Lakeside Mutual decided for
data holder specializations as follows:
In the context of the Customer Management backend,
facing the need to keep and use customer data for a long time,
the API designers at Lakeside Mutual decided to use the Master Data Holder
pattern, introducing a Customer Core service, and neglected the other four types
of information holders,
to achieve a single consolidated view on customer data across systems,
accepting that this Master Data Holder might become a performance bottle-
neck and single point of failure if it is not architected and implemented properly.
«Pattern» «Pattern»
Computation State Creation
Function Operation
«Option»
«Option»
an operation that computes a an operation that
result solely from the input creates states on an
and does not read or write API endpoint and is in
server-side state essence write-only
«Decision»
Responsibility
of an API
Operation
«Option» «Option»
an operation that performs a read-only operation that
one or more activities only finds and delivers data
causing a server-side state without allowing clients to
change change it
«Pattern» «Pattern»
State Transition Retrieval
Operation Operation
The first pattern is State Creation Operation, modeling an operation that cre-
ates states on an API endpoint and is, in essence, write-only. Here, in essence means
that such operations might need to read some provider-internal state—for example,
to check for duplicate keys in existing data before creation. However, their main pur-
pose is state creation.
In the design of State Creation Operations, their impact on coupling should be
considered. Because the provider state is not read, it can become difficult to ensure
consistency. As incidents that clients report happen before they arrive at the provider,
timing needs to be considered in the design as well. Finally, reliability is an important
concern, as messages might appear in a different order or be duplicated at the API
provider.
68 Chapter 3 API Decision Narratives
A A’
The selection of this pattern has the following decision drivers: service granularity is
essential to consider, as large services may contain complex and rich state information,
updated only in a few transitions, while smaller ones may be simple but chatty in terms
of their state transitions. For longer-running process instances, it can be difficult to
keep the client-side state and the states of provider-side backends consistent. In addi-
tion, it is important to consider whether there are dependencies on state changes made
earlier in the process. For example, system transactions triggered by other API clients,
by external events in downstream systems, or by provider-internal batch jobs might
collide with a state change triggered by a State Transition Operation. There is a
trade-off between the two goals of network efficiency and data parsimony: the smaller
messages are, the more messages have to be exchanged to reach a particular goal.
A A’
• What is the optimal number of API message parameters and body parts and an
adequate structure of these representation elements?
• What are the meaning and stereotypes of the representation elements?
For instance, regarding the first question, an HTTP resource API typically uses
the message body to send data to or receive data from the provider (for instance,
rendered as JSON, XML, or another MIME type), and the query parameters of
the URI specify the requested data. In a WSDL/SOAP context, we can interpret this
design issue as how the SOAP message parts should be organized and which data
types should be used to define the corresponding elements in the XML Schema Defi-
nition (XSD). In gRPC, this design issue is about the message structure defined with
Protocol Buffer specifications, for example containing details such as messages and
data types.
Selecting Message Representation Patterns 71
Decisions for this category likely have to be made whenever a message is designed
or refactored. The representation elements transported in the message, including
request parameters and body elements, are considerations in these decisions.
As illustrated in Figure 3.9, this category contains four typical decisions. The first
is on the structure of the parameter representation. Based on this representation, it
can be decided what the meaning and responsibility of message elements are. Next,
it can also be decided whether multiple data elements require additional informa-
tion. Finally, the whole message can or cannot be extended with context information.
«Optional Next»
«Decision»
Subset of High
Number and
Data Records
with the Same
Structure
Required
Figure 3.10 illustrates the typical decision-making options for this decision.
«Pattern» «Pattern»
Atomic Atomic
Parameter Parameter List
«Option» «Option»
scalar representation list representation
«Decision»
Structure of
Parameter
Representation
«Option» «Option»
complex complex representation
representation with with multiple root
one root element elements
«Pattern» «Pattern»
Parameter Tree Parameter Forest
If neither option (scalar or list representation) is applicable, one of two more com-
plex representations should be chosen. If a single root element is present in the data
or can easily be designed for the data to be transmitted, the representation elements
can be wrapped in a hierarchical structure following the Parameter Tree pattern.
As any complex data structure can be placed under a single root element, the
Parameter Tree option is always applicable but might not make much sense if the
data elements are rather unrelated contentwise. If a single tree structure feels awk-
ward or artificial for the data elements to be transmitted, several trees can be grouped
into a list of such structures in the Parameter Forest pattern.
74 Chapter 3 API Decision Narratives
The more complex patterns in this category all use Atomic Parameters to build
up more complex structures. That is, Atomic Parameter List is a sequence of
Atomic Parameters, and the tree leaves in a Parameter Tree are Atomic Param-
eters. The structures in a Parameter Forest are built using the other three pat-
terns. Those uses relations between the patterns are illustrated in Figure 3.11. As
a consequence, the two decisions explained previously need to be recursively made
again for the detailed structures in the complex patterns. For instance, for each data
structure in a Parameter Tree, it must be decided again whether this structure itself
is represented as a scalar, list, or tree. The technology mappings of the patterns are
discussed in Chapter 4.
An Atomic Parameter List can be represented as a Parameter Tree as a wrap-
per structure for transport if the technology used supports no other way to transport
multiple flat parameters. Such a tree has only scalar leaves underneath its root.
There are several shared decision drivers when selecting among the four patterns
in the structure of parameter representation decision.
One obvious force is the inherent structure of the domain model and the system
behavior. To ensure understandability and simplicity, and to avoid unnecessary com-
plexity, it is advisable to stay close to the domain model, both in the code and in
parameter representations in messages. It is important to apply this general advice
carefully—only data that the receiver wants should be exposed to avoid unneces-
sary coupling. For instance, if the domain data element structure is a tree, apply-
ing Parameter Tree is a natural choice, enabling easy traceability from domain
model or programming language data structures to message structures. Similarly,
the intended behavior should be reflected closely: For an Internet of Things (IoT)
scenario in which a sensor sends one data item frequently to an edge node, the most
natural choice is an Atomic Parameter. Decisions on the number of messages and
on each message structure require a careful analysis of when which data element
is required. Sometimes this cannot be deduced analytically, and extensive testing is
required to optimize the message structures.
Selecting Message Representation Patterns 75
«Pattern»
Parameter Forest
«Uses»
«Can Use»
as wrapper «Uses»
structure for
«Pattern» transport «Pattern»
Parameter Tree Atomic
Parameter
«Uses»
All kinds of additional data to be transmitted with the message, such as security-
related data (for example, security tokens) or other metadata (for example, message
and correlation identifiers or error codes), have to be considered here as well. Such
extra information can actually change the structural representation of the message.
For instance, if metadata has to be sent in addition to a Parameter Tree, it might
make sense not to integrate the metadata in the tree but to use a Parameter Forest
with two top-level tree elements instead, the message content and the metadata.
It is not always necessary to transmit entire data elements available in an under-
lying business logic or domain model. To enable better performance, only the rel-
evant parts of the data elements should be transmitted. This optimizes the resource
use (less bandwidth usage and lower memory consumption) and performance of
message processing. For instance, if a client requires salary data stored in a set of
employee data records to perform calculations unrelated to the specific employee,
76 Chapter 3 API Decision Narratives
one could simply transmit all those records in a Parameter Tree. But as only the sal-
ary numbers are needed, sending only those numbers in an Atomic Parameter List
would greatly reduce the message size.
On the other hand, breaking apart data into too many small messages can also
negatively impact resource use, as it increases the network traffic and needs more
bandwidth overall. Thus, a high number of small messages might require more per-
formance for processing many messages overall. This situation gets even worse if the
server has to restore the session state each time a message is processed. For instance,
if the client in the preceding example requires other data from the set of employee
records shortly after the first calculation and sends several successive requests, the
total resource use and performance might be much worse than if the whole set of
selected employee records had been transmitted in the first place.
Sometimes, a number of data elements can be grouped and sent in one message,
again to improve resource use and performance. For instance, if an edge node of a
cloud-based IoT solution collects data from sensors (such as a set of measurements
in a certain time interval), it often makes sense to send this data to the cloud core in
batches rather than sending each data element separately. When performing precal-
culations on the edge, their results might even fit into single Atomic Parameters.
Considering the cacheability and mutability of message payload can help to
improve performance and resource consumption.
Optimizing resource use and performance may have a negative influence on other
qualities, such as understandability, simplicity, and complexity. For instance, an API
that offers one message per specific task to be performed on an employee record
would contain many more operations in the API endpoint than an alternative design
that just allows for transmitting a specified set of employee records in their entirety.
The former option might have a better resource utilization and performance, but the
API design is also much more complex and thus harder to understand.
The request and response message structures are important elements of the API
contract between API provider and API client; they contribute to the shared knowl-
edge of the communication participants. This shared knowledge determines part of
the coupling between API provider and API client, which is discussed as the format
autonomy aspect of loose coupling [Fehling 2014]. For example, one could consider
always exchanging strings or key-value pairs, but such generic solutions increase
the knowledge that is implicitly shared between consumer and provider, leading to
stronger coupling. This would complicate testing and maintenance. It also might
bloat the message content unnecessarily.
Sometimes, only few data elements have to be exchanged in message structures to
satisfy the information needs of the communication participants, for instance, when
checking the status of a processing resource (in the form of a distinct value defined
Selecting Message Representation Patterns 77
a negative impact on the stability of the API design. Important design considerations
that are hard to get right in the first place are involved, one reason being the uncer-
tainty about (future) use cases that API providers and API clients often experience.
Note that in addition to the more conceptual considerations called out in this sec-
tion, many technology decisions also have to be made. This includes supported com-
munication protocols (HTTP, HTTPS, AMQP, FTP, SMTP, and so on) and message
exchange formats such as JSON, SOAP or plain XML, ASN.1 [Dubuisson 2001],
Protocol Buffers [Google 2008], Apache Avro schemas [Apache 2021a], or Apache
Thrift [Apache 2021b]. API query languages such as GraphQL [GraphQL 2021] can
also be introduced.
Element Stereotypes
The decision on the structure of parameters, explained earlier, defines the data trans-
fer representations (DTRs) for request and response messages. However, this deci-
sion does not yet define the meaning of the individual representation elements. Four
element stereotype patterns, shown in Figure 3.12, define the typical design options
for the element stereotypes decision.
«Decision»
Meaning of
Stereotypes of
Message
Elements
There are several decision drivers that apply to any kind of Data Element. When
designing API elements that represent data-centered domain elements such as Enti-
ties, the simplest and most expressive way to map them to APIs is to represent the
Entity fully in the API. Often this is not a good idea, as it increases the number of
processing options for communication participants, which limits the ease of process-
ing the data. Interoperability can be at risk, and API documentation effort increases.
80 Chapter 3 API Decision Narratives
The key decision drivers for Metadata Elements are similar to the ones for
ordinary Data Elements. However, a number of specific additional aspects have to
be considered. If data travels with corresponding type, version, and author infor-
mation, the receiver can use this extra information to resolve ambiguities, which
improves interoperability. If runtime data is accompanied by additional explanatory
data, it becomes easier to interpret and process; on the other hand, this may increase
coupling between the communication parties. To improve ease of use, Metadata
Elements may help the message recipient to understand the message content and
process it efficiently. But messages become larger when Metadata Elements are
included, so runtime efficiency may be negatively affected.
A type of Data Element with a special meaning or responsibility are those ele-
ments that signify identifiers.
Selecting Message Representation Patterns 81
Pattern: id ELEmEnt
Problem How can API elements be distinguished from each other at design time and
at runtime? When applying domain-driven design, how can elements of the
Published Language be identified?
Solution Introduce a special type of Data Element, a unique Id Element, to identify API
endpoints, operations, and message representation elements that have to be
distinguished from each other. Use these Id Elements consistently throughout
API Description and implementation. Decide whether an Id Element is globally
unique or valid only within the context of a particular API.
The Link Element pattern shares its decision drivers with Id Element, as essen-
tially all Link Elements are remotely accessible Id Elements. The opposite does
not hold; some identifiers used in APIs do not contain network-accessible addresses.
For example, consider a domain data element that should not be remotely acces-
sible by the client, but still has to be referenced (for instance, a key data element in
the backend or in a third-party system). In such a situation, a URI cannot be used.
It can be challenged whether or not such elements should be handed out to clients at
all. Sometimes this might be a bad design choice, whereas in other cases, it might be
necessary. Consider for instance a backend “Correlation Identifier” [Hohpe 2003] or
a proxy (surrogate) for a Correlation Identifier: it must be passed along to the client
in order to be applicable.
«Data Element»
«Data Element» customers
CustomerResponseDto
AddressDto
rstName: String
streetAddress: String lastName: String
postalCode: String
city: String «Id Element»
customerId: String
To let clients interact with the customer master data, the CustomerInforma-
tionHolder is implemented as an Information Holder Resource, specifically
a Master Data Holder that exposes several operations. In these operations, the
request and response messages transport different Data Elements, for example, of
customer data. The implementation classes are not exposed directly; instead, DTOs
are used. Unlike the entities, the DTOs also hold Id Elements and Link Elements
that let clients retrieve more data.
Because Lakeside Mutual serves a large number of customers, the result of the
getCustomers Retrieval Operation uses Pagination, a pattern we have not seen
so far, to let API clients navigate the data in manageable chunks.
Pagination and other patterns related to API quality are featured later in the next
two decision narratives.
84 Chapter 3 API Decision Narratives
How can we achieve a certain level of quality of the offered API while at the same
time utilizing the available resources in a cost-effective way?
The quality of an API has many dimensions, starting with the functionality
described in the API contract but also including reliability, performance, security,
and scalability. Some of these technical qualities are referred to as quality of service
(QoS) properties. QoS properties might be conflicting and almost always need to be
balanced with economic requirements such as cost or time to market.
The guaranteed QoS does not have to be the same for all clients. Most decisions
in this category have to be made for combinations of API clients and APIs accessed
by these clients. Many decisions can be made for large groups of these combina-
tions, such as all clients with freemium access to an API or all clients accessing a
specific API.
The main decisions related to quality governance are shown in Figure 3.14.
«Category»
Quality
«Decision» «Decision»
Handling of Avoid
Referenced Data Unnecessary Data
Transfer
«Decide for some instances of» «Decide for some instances of»
«Consider If Not
Decided Yet»
«Consider If Not «Consider If Not
Decided Yet» Decided Yet»
«Decision»
Client Identification
and Authentication
API quality has to be governed and, as needed, improved. In this section, we look
at governance and management; the next one suggests quality improvements. The
themes of the decisions about the patterns in this category are as follows:
«Option»
identification and
authentication via «Option»
«Pattern» «Decision» «Practice»
shared secret, secured authorization via
API Key Client Authorization
with secret key dedicated protocol
Combined with Identification Protocol
Secret Key and
Authentication
«Realizes» «Realizes»
«Practice»
Authentication
The first and simplest option is to decide that secure identification and authenti-
cation are not needed, which is suitable, for instance, in nonproduction system APIs;
for APIs in controlled, nonpublic networks with a limited number of clients; or for
Public APIs with a limited number of clients and no great risks in case of abuse or
excessive use.
The obvious alternative is to introduce an authentication mechanism for the API.
An API Key that identifies the client is a minimalistic solution to this problem.
If security is an important issue, API Keys are insufficient on their own. In con-
junction with an additional secret key that is not transmitted, API Keys can be used
to securely authenticate an API client. The API Key identifies the client, and an
Governing API Quality 87
additional signature made with the secret key, which is never transmitted, proves the
identity and ensures that the request was not tampered with.
Many complements and alternatives to API Keys exist, as security is a challeng-
ing, multifaceted topic. For instance, OAuth 2.0 [Hardt 2012] is an industry-standard
protocol for authorization that is also the foundation for secure authentication
through OpenID Connect [OpenID 2021]. Another example of a full-fledged authen-
tication or authorization protocol is Kerberos [Neuman 2005], an authentication
protocol that is often used inside a network to provide single sign-on. In combina-
tion with Lightweight Directory Access Protocol (LDAP) [Sermersheim 2006], it can
also provide authorization. LDAP itself also offers authentication features, so LDAP
can be used as authentication and/or authorization protocol. Examples of point-to-
point authentication protocols are Challenge-Handshake Authentication Protocol
(CHAP) [Simpson 1996] and Extensible Authentication Protocol (EAP) [Vollbrecht
2004].
A number of forces have to be considered in this decision. First of all, the level
of required security is important. If secure identification and authentication are
required, it is insufficient to choose either no secure identification and authentica-
tion needed or API Keys. API Keys help to establish basic security. Although they
require following a registration process, API Keys bring only a slight degradation in
terms of ease of use for clients once they have been obtained (compared to no secure
identification and authentication). The other options are less easy to use, as they
require dealing with more complex protocols and setting up the required services
and infrastructure. The management of user account credentials required in authen-
tication and authorization protocols can be tedious both on the client and provider
side; this is avoided in all options using API Keys, including its combination with a
secret key.
With regard to performance, the decision that secure identification and authenti-
cation is not needed has no overhead. API Keys have a slight overhead for processing
the keys, and their combination with a secret key requires some more processing
slightly reducing the performance. Authentication and authorization protocols tend
to have more overhead, as they also offer additional features (such as contacting a
trusted third party in Kerberos or authorization in OAuth or LDAP). Finally, the API
Key option decouples the client making an API call from the client’s organization,
as using the customer’s account credentials would needlessly give system administra-
tors and developers full account access. This problem could be mitigated in authenti-
cation and authorization protocols by establishing subaccount credentials that only
enable API access for an API client but do not offer any other privileges of the cus-
tomer’s account.
88 Chapter 3 API Decision Narratives
$$$
«Decision»
Metering and
Charging for API
Consumption
«Option» «Option»
Yes No «Consider If Not Decided Yet»
«Pattern» «Practice»
Rate Limit Authentication
«Can Use»
«Pattern» «Pattern»
Pricing Plan Freemium Model
«Can Be Combined With»
The major drivers for this decision are usually economic aspects, such as pric-
ing models and selecting a variant of the pattern that best suits the business model.
The benefits of applying the pattern should be contrasted with the efforts and
costs required to meter and charge customers. Accuracy is central, as API custom-
ers expect to be billed only for the services they actually have consumed. Accurate
metering requires an adequate meter granularity. Because metering and charging
records contain sensitive information about customers, extra protection has to be
provided to ensure security.
The alternative to using Rate Limits is to do nothing to prevent API clients from
excessive API usage. This makes sense in situations in which the problem is assessed
as unlikely to turn into a severe issue. For example, if all clients are in-house clients
or trusted partners, the overhead of a Rate Limit might not be justified.
The two alternatives, as well as the link to client identification and authentication
(and the authentication practices), are shown in Figure 3.18.
«Decision»
Preventing API
Clients From
Excessive
Usage
«Can Use»
«Practice»
Authentication
Figure 3.18 Prevent API clients from excessive API usage decision
The major forces to be considered in this decision are as follows: A certain level of
performance has to be maintained by the provider (sometimes even formally guaran-
teed in a Service Level Agreement); performance could be compromised if clients
abuse the API. Means for supporting client awareness of Rate Limits are required so
that clients can find out how much of their limits they have used up at a given point
in time. Establishing Rate Limits helps the provider to support qualities related to
reliability because they make it harder for clients to abuse the API in a way that puts
these qualities at risk. All these potential benefits must be contrasted to the impact
92 Chapter 3 API Decision Narratives
and severity of risks of API abuse and economic aspects. Introducing Rate Limits
produces costs and can be perceived negatively by clients. Thus, it has to be judged
whether the risks of API abuse imposed by a few clients are higher than the risks and
costs associated with introducing Rate Limits for all clients.
There are a number of typical variants of the pattern: SLAs only used for internal
use, SLAs with formally specified SLOs, and SLAs with only informally specified
SLOs.
«Decision»
«Pattern» «Pattern» «Pattern» Explicit
Rate Limit Pricing Plan API Description Specification of
Quality
Objectives and
Penalties
«Option» «Option»
Yes No
«Can Use» «Can Use» «Can Use» «Consider If Not Decided Yet»
«Practice»
SLA with SLA with SLA only for
Authentication
formally informally internal use
specified SLOs specified SLOs
Figure 3.19 SLAs and explicit specification of quality objectives and penalties decision
A Pricing Plan and Rate Limit should refer to the Service Level Agreement if
it is used. Like these patterns, a Service Level Agreement requires means for iden-
tifying and authenticating clients; usually, authentication practices such as API Keys
or authentication protocols have to be used as well.
Several main decision drivers steer this decision. It relates to business agility and
vitality, as the business model of an API client might rely on one or more of the pre-
viously named qualities of a particular service. Attractiveness from the consumer’s
point of view can be higher if guarantees about qualities are provided and commu-
nicated to the client. However, this must be contrasted with possible issues related to
cost-efficiency and business risks from a provider point of view. Some guarantees are
required by government regulations and legal obligations, such as those related to
personal data protection. Typical aspects that are candidates for guarantees in SLAs
are availability, performance, and security.
94 Chapter 3 API Decision Narratives
Note that some architectural decisions typically are revised as a product or service
evolves. In our insurance case, an SLA is actually introduced at a later stage, as we
will see in the presentation of the SLA pattern in Chapter 9.
Communication of Errors
A common quality concern for APIs is how to report and handle errors, as this has
direct impacts on aspects such as avoiding and fixing defects, costs of defect fixing,
robustness and reliability problems due to unfixed defects, and so on. If an error
occurs on the provider side, it can be due to an incorrect request, invalid permissions,
or numerous other problems that could be the fault of the client, the API implemen-
tation, or the underlying IT infrastructure.
One option is not to report (and then handle) an error at all, but this is usually
not advisable. A common solution if only one protocol stack is used (such as HTTP
over TCP/IP) is to leverage the error-reporting mechanisms of these protocols, for
instance, status codes in HTTP (protocol-level error codes). This does not work
if error reporting has to cover multiple protocols, formats, and platforms. In such
cases, the Error Report pattern is eligible.
The decision is illustrated in Figure 3.20. The main decision drivers to introduce
any kind of error reporting are the help in fixing defects and the increased robust-
ness and reliability that this promises. Error reporting leads to better maintain-
ability and evolvability. Detailed explanations of errors reduce the effort to locate
the root cause of a defect; consequently, the Error Report pattern often is more
effective than simple error codes. The target audiences of fault information include
developers and operators, but also help desk and other supporting personnel.
Thus, Error Reports should be designed to reach high expressiveness and achieve
meeting the target audience’s expectations. Error Reports are usually designed
to score well with regard to interoperability and portability, compared to simple
error codes. However, rather elaborate error messages can reveal information that
is problematic with regard to security, as disclosing more information about sys-
tem internals opens up attack vectors. An Error Report requires more work if
internationalization is required because the more detailed information contained
in the Error Report has to be translated.
«Decision»
Communication
of Errors
«Do Nothing»
Error Reporting Protocol-Level
Do Nothing
Error Codes
«Can Be Combined With»
«Decision»
Exchange of
Context
Information
Required
«Option» «Option»
Yes No
This decision narrative covered the theme API quality governance; the next set of
decisions aims at improving certain qualities, such as performance.
Pagination
Sometimes complex representation elements can contain large amounts of data that
is repetitive in nature (for instance, record sets). If only a subset of this information
at a time is required at the client, it might be better to send the information in small
chunks rather than in one large transmission. For example, consider thousands of
records being contained in the data, but a client displaying the information pagewise
with 20 records per page; user input is required to advance to the next page. Display-
ing only the current page and maybe prefetching one or two pages in either stepping
direction might be far more efficient in terms of performance and bandwidth use
than downloading all data records before even starting to display the data.
Deciding for API Quality Improvements 99
The starting point is that API designers have decided to apply either Parame-
ter Tree or Parameter Forest. Both patterns are used to represent complex data
records. In such cases, the designers should think about the following decision (illus-
trated in Figure 3.22):
«Pattern» «Pattern»
Parameter Tree Parameter Forest
«Decision»
Subset of High Number of Data
Records with the Same Structure
Required
«Option» «Option»
Yes No
«Pattern»
Pagination «Do Nothing»
Do Nothing
«Has Variant»
«Has Variant» «Has Variant» «Has Variant»
Pattern: Pagination
Problem How can an API provider deliver large sequences of structured data without
overwhelming clients?
Solution Divide large response data sets into manageable and easy-to-transmit chunks
(also known as pages). Send one chunk of partial results per response message,
and inform the client about the total and/or remaining number of chunks. Provide
optional filtering capabilities to allow clients to request a particular selection of
results. For extra convenience, include a reference to the next chunk/page from the
current one.
«Pattern»
Pagination
The pattern has the following relations to the patterns presented earlier:
• An Atomic Parameter List is usually used for its request message containing
the query parameters.
Deciding for API Quality Improvements 101
• A Parameter Tree or a Parameter Forest is usually used for the data struc-
turing in its response messages.
There are several key decision drivers when applying Pagination. The structure
of data elements or of the additional data that have to be sent with the message
needs to be repetitive in nature (contain data records, that is). The variability of the
data should be considered: Are all data elements identically structured? How often
do data definitions change?
Pagination aims to substantially improve resource consumption and perfor-
mance by sending only the data needed at the moment as fast as possible to the API
client. A single large response message might be inefficient to exchange and process.
In this context, data set size and data access profile (derived from the user wants
and needs), especially the number of data records required to be available to an API
client (immediately and over time), have to be considered. Especially when returning
data for human consumption, not all data may be needed immediately.
Also related to resource consumption, the memory available for a request (on both
API provider and API client sides) as well as the capacity of the network have to be
considered. Network and endpoint processing capabilities should be used efficiently,
but all results should be transferred and processed accurately and consistently.
Common text-based message exchange formats (for instance, expressively tagged
XML or JSON) incur high parsing costs and transfer data size due to verbosity and
overhead of the textual representations of the data. Some of this overhead can be
significantly reduced by using binary formats such as Apache Avro or Protocol Buff-
ers. However, many of these formats require dedicated serialization/deserialization
libraries, which may not be available in all consumer environments, for example, API
clients in Web browsers. The pattern is particularly eligible in such cases.
102 Chapter 3 API Decision Narratives
API providers often serve many different clients. It can be hard to design API oper-
ations that provide exactly the data required by all these clients. Some of them might
use only a subset of the data offered by the operations; other clients might expect
more data. The information need might not be predictable before runtime. A possi-
ble way to solve this problem is to let the client inform the provider at runtime about
its data fetching preferences. A simple option to do this is to let the client send a list
of its desires.
A simple list of wishes is not always easy to specify, for example, if a client wants
to request only certain fractions of deeply nested or repetitive parameter structures.
An alternative solution that works better for complex parameters is to let the client
send a template (or mock object) expressing the wishes as examples in its request.
While Wish Lists are typically specified as Atomic Parameter Lists and lead to
a reply based on a Parameter Tree, Wish Template typically performs the specifi-
cation of the wish in a mock Parameter Tree whose structure is also used for the
response.
104 Chapter 3 API Decision Narratives
For example, the provider could supply a fingerprint for each resource accessed,
which the client can then include in a subsequent request to indicate which “version”
of the resource it already has cached locally so that only newer versions are sent.
In other situations, an analysis of the usage of the already-deployed API might
reveal that clients are issuing many similar requests and that individual responses are
returned for one or more of these calls. These batches of requests may have a nega-
tive impact on scalability and throughput. In such situations, the Request Bundle
pattern is eligible.
Figure 3.24 summarizes the decision on how to avoid unnecessary data transfer.
«Decision»
Avoid
Unnecessary
Data Transfer
«Option»
No data transfer «Option» «Option» «Option» «Option»
reduction Use simple list to Use a structured Make data transfer Bundle multiple
possible or convey which template to dependent on a requests in a container
wanted information is convey which condition in the message
required information is request
required
«Pattern»
Rate Limit
For many operations, no data transfer reduction is possible or wanted for the
target operation(s). Alternatively, unnecessary data transfer can be avoided through
one of the two patterns Wish List and Wish Template, which both inform the pro-
vider about required data at runtime. Other alternatives are Conditional Request
to avoid repeated responses to the same requests and Request Bundle to aggregate
multiple requests in a single message.
The combination of Conditional Request with either Wish List or Wish Tem-
plate is a rather useful choice to indicate which subset of resources is requested in
case the condition evaluation states that the resource should be sent again. Request
Bundle can in principle be combined with each of the prior alternatives Condi-
tional Request or either Wish List or Wish Template. However, a combination
of two or even three of the patterns increases the complexity of the API design
and programming substantially for rather little gains, as all four patterns influence
a similar set of desired qualities positively. Figure 3.25 shows the possible pattern
combinations.
106 Chapter 3 API Decision Narratives
«Pattern»
Request Bundle
«Pattern» «Pattern»
Wish List Wish Template
«Can Be Combined With» «Can Be Combined With»
The main decision driver for this decision concerns the individual information
needs of clients, which have to be analyzed in order to find out which of the patterns
(and maybe even which combinations) are applicable and promise to have enough
benefits. Consider situations where data transfer over the network is perceived as a
potential bottleneck. In such cases, data parsimony can further drive the decision.
Data parsimony is an important general design principle in distributed systems, and
the four patterns can help to enhance parsimonious ways of data transmission.
Selecting any of the four patterns usually has a positive influence on the Rate
Limit and on bandwidth use, as less data is transferred. This likely will also improve
the performance, as transferring all data elements to all clients all the time, even
to clients that have only a limited or minimal information need, wastes resources
(including response time, throughput, and processing time).
Security can be a driver not to apply the patterns Wish List and Wish Template.
Enabling clients to provide options regarding which data to receive may unwit-
tingly expose sensitive data to unexpected requests or generally open up additional
attack vectors. For instance, sending long data element lists or using invalid attribute
Deciding for API Quality Improvements 107
Sample decision outcome. How does the Lakeside Mutual APIs provide a suited
message granularity and call frequency? The architects and designers chose
patterns as follows:
In the context of the Customer Management frontend for staff and agent use
cases,
having to deal with large amounts of customer records,
the API designers at Lakeside Mutual selected the Wish List pattern and did not
pick any other pattern from this section
so that response messages are small,
accepting that the wishes have to be prepared on the client side and processed on
the provider side, and that additional metadata is required.
Closely related to the decisions about message size optimization is the decision
about inlining or splitting structured data (complex data with multifaceted relations
between its parts, that is). We investigate two alternative patterns tackling this design
issue next.
There are two major options for this decision, shown in Figure 3.26.
«Pattern»
Data Element
«Optional Next»
«Decision»
Handling of
Referenced Data
«Option»
Links are provided to
«Option» look referenced data
Referenced data is up with separate calls
«Pattern» embedded in the
Embedded Entity message representation
«Pattern»
Linked
Information
Holder
«Can Use»
for providing an additional level
of indirection to decouple
«Requires»
resource clients and providers
«Pattern» «Pattern»
Link Lookup Resource Link Element
«Requires»
One option to address this problem is to embed the data of the referenced data
record in the Data Element to be sent over the wire.
The alternative is to make the referenced data accessible remotely and point at it,
introducing a Link Element to the message:
Figure 3.26 illustrates that this pattern can use a Link Lookup Resource for pro-
viding an additional level of indirection to decouple resource clients and providers.
Both Linked Information Holder and Link Lookup Resource require the use of
Link Elements.
It is possible to combine the two patterns, for instance, when using a top-level
Embedded Entity that itself uses Linked Information Holders for (some of) its
referenced data records.
As decision drivers, performance and scalability often play a major role. Both
message size and the number of calls required to perform an integration should be
low, but these two desires stand in conflict with each other.
Modifiability and flexibility have to be considered as well: information elements
contained in structured self-contained data might be hard to change because any
local updates have to be coordinated and synchronized with updates to related data
structures and the API operations that send and receive them. Structured data that
contains references to external resources usually is even harder to change than self-
contained data as there are more consequences and (external) dependencies for
clients.
Embedded Entity data sometimes gets stored for a while, whereas links always
refer to the latest updates in the data. Thus, accessing data when it is needed via links
is positive for data quality, data freshness, and data consistency. In terms of data
privacy, a relationship source and target might have different protection needs—for
example, a person and the credit card information belonging to this person. This
has to be considered, for instance, before embedding the credit card information in a
message requesting the person’s data.
110 Chapter 3 API Decision Narratives
Sample decision outcome. Does Lakeside Mutual prefer many small or few large
messages? They decided as follows:
In the context of the customer self-service channel,
facing the need to expose the customer aggregate that contains two entities (and
works with two database tables), the API designers at Lakeside Mutual decided
to use the Embedded Entity pattern
and neglected Linked Information Holder
so that all related data is transmitted in a single request,
accepting that the address data is transferred although not needed in some use
cases.
The patterns API Key, Context Representation, and Error Report are used
mainly in the elaboration (or Define) phase, which is covered in Chapter 6, “Design
Request and Response Message Representations.” Chapter 7, “Refine Message
Design for Quality,” then covers the construction (or Design) phase, containing the
patterns Conditional Request, Request Bundle, Wish List, Wish Template,
Embedded Entity, and Linked Information Holder. Finally, the Pricing Plan,
Rate Limit, and Service Level Agreement patterns are covered in Chapter 9, as
they mainly concern the transition phase of an API.
This completes the coverage of decisions and pattern options about API quality
(in this book). Next, we identify decisions required and patterns available to organ-
ize API evolution.
API providers and clients have to balance different, conflicting concerns in order
to follow their own life cycles; a certain amount of autonomy is required to avoid
tight coupling between them. In response to this conflict, the patterns presented here
jointly support API owners, designers, and users who seek to answer the following
question:
What are the governing rules balancing stability and compatibility with maintain-
ability and extensibility during API evolution?
As illustrated in Figure 3.27, API evolution centers around three decisions. The
first is whether the API supports some explicitly defined version identification
scheme, and if so, how version information is exchanged. The second decision is
on when and how new versions of an API should be introduced and old versions are
decommissioned. It offers three alternative strategies as decision options. Finally, it
can be decided whether or not any of the three strategies is augmented with an addi-
tional experimental preview. All those decisions are typically made at the API level.
«Category»
Evolution
«Decide for some instances of» «Decide for some instances of» «Decide for some instances of»
«Basic Concept»
API
Figure 3.28 illustrates the typical options for this decision. First, it has to be
decided whether an explicit version identification and transmission scheme is used.
The pattern Version Identifier covers this option. Next, Semantic Versioning
describes the use of a structured Version Identifier that separates breaking from
non-breaking changes.
«Option»
Define no scheme for «Option» «Option»
version identification and Use well-known,
Use an explicit version identification
transmission structured version
and transmission scheme
identifier
«Can Use»
to transmit identifier in a message
«Pattern»
Metadata
Element
exactness of identification. When an API uses it, its clients can rely on the syntax and
semantics defined in the specified API version; the message exchanges are interoper-
able as long as the Version Identifier stays the same. This way, client-side impact is
minimized: the client can safely assume that “breaking changes” will only be intro-
duced in subsequent versions. Furthermore, API providers want to avoid accidentally
breaking compatibility: if a Version Identifier is part of the message, recipients
can reject a message with an unknown version number. Finally, explicit versioning
makes it easier for API providers to manage their APIs, as it provides traceability of
API versions in use: API providers can monitor how many and which clients depend
on a particular API version.
Version Identifiers should be accurate and exact. Breaking changes will require
changes to the clients; thus, they are closely linked to considerations about the cli-
ent-side impact of software evolution steps. To make it impossible to accidentally
break backward compatibility, recipients should be able to reject a message based on
unknown version numbers. Finally, it should be considered that Version Identifiers
can help to establish traceability of API versions in use.
to achieve that breaking changes are spotted as soon as possible and maintenance
is eased,
accepting that metadata has to be transmitted and API descriptions require
updates as versions evolve.
Figure 3.29 illustrates the typical choices for this decision. The patterns explained
in this section are alternative options, providing different strategies to introduce and
decommission versions.
«Option»
Support two or more «Option» «Option»
incompatible versions of Support API Decommission API versions
the API in production at versions for a as early as possible
any time predefined lifetime
v1.1
Pattern: LimitEd LifEtimE guarantEE
Problem How can a provider let clients know for how long they can rely on the published
version of an API?
Solution As an API provider, guarantee to not break the published API for a fixed
timeframe. Label each API version with an expiration date.
Applying this pattern means that a limited number of API versions are kept in
production. The goal is to guarantee that API changes do not lead to undetected
backward-compatibility problems between clients and the provider, especially with
regard to their semantics. It does so through a compromise: changes to the client
caused by API changes are minimized as multiple versions are supported, and clients
can stay on the last version for a defined time. But the pattern also limits the number
of API versions supported by API providers, thereby minimizing the maintenance
effort for supporting clients relying on these API versions. Thus, the pattern guaran-
tees that API changes do not lead to undetected backward-compatibility problems
between clients and the provider.
Limited Lifetime Guarantee achieves this combination of force impacts through
a concrete date in the lifetime guarantee that helps to make client-side changes caused
by API changes more plannable. It also limits the maintenance effort to support old
clients that API providers have to plan for.
The Aggressive Obsolescence pattern can be used for phasing out existing fea-
tures as early as possible.
v1.3 v2.1
When releasing a new API version, the oldest one that still runs in production is
retired (which is the second last one by default). As a variant, more than two ver-
sions—for instance, three—can be supported. In such cases, the pattern variant “N
in Production” is chosen. To maintain the character and benefits of this pattern,
however, it is crucial that the number N remains small.
Two in Production allows the API provider and the client to follow different
life cycles so that a provider can roll out a new API version without breaking clients
using the previous API version. Two in Production’s impact on forces resolution is
similar to that of Limited Lifetime Guarantee. The difference is that two (or in the
general case, N) version are supported in parallel, which brings a sound compromise
to the goal conflicts between clients and provider. As an additional benefit for provid-
ers, the pattern enables the ability to roll back to an old API version if a new version
is not accepted by clients due to bugs, poor performance, or a dissatisfying developer
experience.
118 Chapter 3 API Decision Narratives
Finally, to ease the design of new APIs, gain experience, and gather feedback, the
Experimental Preview pattern can be applied to indicate that no API availability
and support guarantees are given, but the API can be used opportunistically with the
objective to gather feedback (provider) and learn early (client).
«Option»
Do not offer «Option»
API previews Offer API previews
This pattern can be applied to support innovations and new features. Such show-
casing raises the awareness of a new API (version), facilitates feedback, and gives
the customers time to decide whether to use the new API and initiate development
projects.
An Experimental Preview is an alternative to one or more official versions. It is
eligible when API providers do not want to manage and support many API versions
in order to focus their efforts.
Consumers want to learn early about new APIs or API versions so that they can
plan ahead, build innovative products, and influence the API design. With regard to
planning, clients especially want stable APIs in order to minimize change effort.
Decisions about API Evolution 119
v0.1
v1.2
?
Pattern: EXPErimEntaL PrEViEW
Problem How can providers make the introduction of a new API (version) less risky for
their clients and obtain early adopter feedback without having to freeze the API
design prematurely?
Solution Provide access to an API on a best-effort base without making any commitments
about the functionality offered, stability, and longevity. Clearly and explicitly
articulate this lack of API maturity to manage client expectations.
Sample decision outcome. The API product owner at Lakeside Mutual decided
as follows:
In the context of the offer quotation API in the policy management backend,
facing the need to support multiple API clients with different release cycles,
the API designers at Lakeside Mutual decided both for the Two in Production
pattern and the Experimental Preview pattern
to achieve that clients have a choice and gain time to migrate when breaking
changes arise (and can play with upcoming features),
accepting that two versions have to be operated and supported simultaneously.
The patterns on API evolution are covered in Chapter 8, “Evolve APIs”. They
mainly concern the transition phase (and later phases) of an API.
120 Chapter 3 API Decision Narratives
The returned response now contains only the requested fields (see the Wish List
pattern in Chapter 7, “Refine Message Design for Quality,” for the full example):
{
"customerId": "gktlipwhjr",
"birthday": "1989-12-31T23:00:00.000+0000",
"postalCode": "8640"
}
All operations are guarded by API Keys, which are represented by the Authori-
zation header in the preceding command. In the Customer Core service, several
requests can be combined into one as a Request Bundle. Failures are communicated
with Error Reports. In the following call, an invalid-customer-id is used:
An Error Report informs the client that this customer was not found:
{
"timestamp": "2022-02-17T11:03:58.517+00:00",
"status": 404,
"error": "Not Found",
"path": "/customer/invalid-customer-id"
}
Interlude: Quality and Evolution Patterns in the Lakeside Mutual Case 121
For more examples of API Keys and Error Reports, please refer to the pattern
texts in Chapter 6.
Many response messages contain either Embedded Entity or Linked Informa-
tion Holders. For example, in the Policy Management backend, the CustomerDto
contains a nested representation of all customer policies. However, many clients
may not be interested in the policies when they access the customer resource. To
avoid sending large messages containing lots of data that is not processed on the cli-
ent side, a Linked Information Holder is used that refers to a separate endpoint
returning the customer policies:
Summary
In this chapter, we identified pattern-related architectural decisions required during
API design and evolution, covering the following topics:
3. Are the Lakeside Mutual developers somewhat disconnected from the architects and the product owner
of this sample case?
Summary 123
The Patterns
This part of the book presents our catalog of patterns for API design and evolution.
Complementary to Chapter 3, “API Decision Narratives,” in Part 1, it does not have
to be read page by page but serves as a reference.
The catalog is organized along the four phases of the Align-Define-Design-Refine
(ADDR) process introduced in Principles of Web API Design: Delivering Value with
APIs and Microservices [Higginbotham 2021]:
• In the early stages, the API scope is derived from and aligned with client goals
and other requirements, as, for instance, articulated in user stories or job sto-
ries. We briefly summarize the related foundation patterns that are eligible in
this phase.
• Still at an early stage of the API design, endpoints and their operations are
defined on a rather high level of abstraction and elaboration. Our responsibility
patterns come into play in this phase.
• Next, technical details and technology bindings are designed. This is where
our message structure and API quality patterns have their place.
• Finally, the API designs and their implementations are continuously refined
during API evolution. Additional quality patterns can also be applied in this
step, often in the form of API refactoring (to patterns).
The progress with the API design is continuously (and incrementally) documented
throughout the design and evolution steps. Appendix A, “Endpoint Identification
125
126 Part 2 The Patterns
and Pattern Selection Guides” explains how the four ADDR phases and its seven
steps (for instance, “Model API profiles”) and our patterns relate to each other.
The chapter structure of this part comes from these considerations. Each chapter
targets at least one role in our target audience:
Pattern Language
Introduction
In Part 1, we learned that remote APIs have become an important feature of modern
distributed software systems. APIs provide integration interfaces exposing remote
system functionality to end-user applications such as mobile clients, Web applica-
tions, and third-party systems. Not only end-user applications consume and rely on
APIs—distributed backend systems and microservices within those systems require
APIs to be able to work with each other as well.
Lakeside Mutual, a fictitious insurance company, and its microservices-based
applications provided us with an example case. We saw that API design and evo-
lution involve many recurring design issues to resolve conflicting requirements and
find appropriate trade-offs. Decision models for groups of related issues presented
options and criteria to guide us through the required design work. Patterns appeared
as alternative options in these decisions.
This chapter takes the next step. It starts with a pattern language overview and
then proposes navigation paths through the language. It also introduces a first set
of basic scoping and structuring patterns. Having read this chapter, you will be
able to explain the scope of our pattern language (in terms of topics covered and
architectural concerns) and find patterns you are interested in (for instance, by pro-
ject phase). You will also be able to characterize the API under construction by its
visibility and integration type by way of foundation patterns and know about the
basic structure patterns that constitute the syntactic building blocks of request and
response messages (and many of the other patterns in our language).
127
128 Chapter 4 Pattern Language Introduction
Should complex data whose parts have containment or other domain-level rela-
tions be embedded in message representations, or should links be provided to
look up this data with separate calls to other operations in the same (or other)
API endpoints?
Request Message
curl –X GET "http://localhost:8080/customers/rgpp0wkpec" –H "accept */*"
Frontend Backend
Response Message
HTTP 200/OK
{
"_links": [
"deprecation": "string“
"href": "string"
],
"birthday": "1982-02-12T09:10:07.370Z",
"moveHistory": [
{
"city": "Sample City", Decision required about
"postalCode": "aZipCode", moveHistory data:
"streetAddress": "Road 1"
} embed in body payload
] or provide a link to it?
}
Figure 4.1 Exemplary API call: Exchanged messages and their structure
Two of our patterns offer alternative answers to this question: Embedded Entity
(shown in Figure 4.1) and Linked Information Holder. Embedded Entity injects
nested data representations into the payload, whereas a Linked Information
Holder places hyperlinks in the payload. In the latter case, the client has to follow
these hyperlinks to obtain the referenced data in subsequent requests to the endpoint
location found in the links. The chosen combination of these two patterns has a
130 Chapter 4 Pattern Language Introduction
strong impact on the API quality. For instance, message size and number of interac-
tions influence both performance and changeability. Both patterns are valid choices,
depending on network and endpoint capabilities, information needs and data access
profiles of clients, backend location of the source data, and so on. These criteria,
therefore, are pattern selection and adoption forces. We will come back to these pat-
terns and their forces in Chapter 7, “Refine Message Design for Quality.”
• When and Why to Apply establishes the context and preconditions for pattern
eligibility, followed by a problem statement that specifies a design issue to be
resolved. Different forces on the design explain why the problem is hard to
solve. Architectural decision drivers and conflicting quality attributes are often
referenced here; a nonsolution may also be pointed out.
• The How It Works section presents a conceptual, generalized solution to the
design question from the problem statement that describes how the solution
works and which variants (if any) we observed in practice.
• The Example section shows how the solution can be implemented in a concrete
application context, for instance, when working with a particular technology
set such as HTTP and JSON.
• The Discussion section explains to what extent the solution resolves the pat-
tern forces; it may also include additional pros and cons and identify alterna-
tive solutions.
• The Related Patterns section points to the next patterns that become eligible
and interesting once a particular one has been applied.
• Finally, additional pointers and references are given under More Information.
Navigating through the Patterns 131
Coming back to our two exemplary patterns, Linked Information Holder and
Embedded Entity are documented in this format in Chapter 7.
Note that using a pattern does not dictate a particular implementation but leaves
a lot of flexibility for its project-context-specific adoption. In fact, patterns should
never be followed blindly but should be seen as a tool or guide. A product- or project-
specific design can satisfy its concrete, actual requirements only if it knows them
(which is hard for a generalized artifact such as a pattern).
1. This “ask for one, get three” tactic is an exception to our general rule, “if in doubt, leave it out”
[Zimmermann 2021b], fortunately only on the meta-level. Hopefully, standards committees and API
designers stick to this rule better than we do ;-).
132 Chapter 4 Pattern Language Introduction
Evolution Patterns:
«Basic Concept» * Version Identifier
API-Level Patterns: * Semantic Versioning
* API Description API
* Experimental Preview
* Pricing Plan - name: String * Aggressive Obsolescence
* Rate Limit - version: String * Limited Lifetime Guarantee
* Service Level Agreement - description: String * Two in Production
Endpoint Patterns:
* Processing Resource
* Information Holder Resource «Basic Concept» «Basic Concept» Operation-Level Patterns:
* Processing Resource Endpoint Operation * State Creation Operation
* Information Holder Resource * Retrieval Operation
* Operational Data Holder - name: String * State Transition Operation
* Master Data Holder - responsibilityPattern: String * Computation Function
* Reference Data Holder
* Link Lookup Resource
* Data Transfer Resource
0..1
«Basic Concept» «Basic Concept»
Message-Level Patterns
Request Message Payload Response Message Payload
(most impact on request):
* API Key - protocolHeaders: NameAndValueSet - protocolHeaders: NameAndValueSet
* Conditional Request - requestPayload: RepresentationElements - responsePayload: RepresentationElements
* Request Bundle
* Wish List
* Wish Template
Call to action: When being confronted with an API design task, ask yourself
which of these scopes you are about to deal with and refer to Figure 4.2 to find
patterns of interest for this task.
• Responsibility patterns: What is the architectural role played by each API end-
point? What are the operation responsibilities? How do these roles and respon-
sibilities impact service decomposition and API granularity?
• Structure patterns: What is an adequate number of representation elements
for request and response messages? How should these elements be structured?
How can they be grouped and annotated?
• Quality patterns: How can an API provider achieve a certain level of design
time and runtime qualities while using its resources in a cost-effective way?
How can the API quality trade-offs be communicated and accounted for?
• Evolution patterns: How can life-cycle management concerns such as support
periods and versioning be dealt with? How can backward compatibility be
promoted and unavoidable breaking changes be communicated?
Call to action: Think about an API design issue you were confronted with recently.
Does it fit in any of the preceding categories? Do any of the questions and pattern
names suggest that the pattern might be able to resolve the issue? If so, you may
want to go to the respective chapter and pattern right now (and return here later).
If you need more information, you can consult the cheat sheet in Appendix A.
2. https://api-patterns.org
134 Chapter 4 Pattern Language Introduction
4
API Visibility and Integration Types
AP Basic Message Structure
5
Define Endpoint Types
and Operations
6
Design Request and Response
Message Representations Information Processing Data Transfer
Holder Resource Resource
Resource
Data Metadata Id Element Link Element State Creation Retrieval State Transition
Element
Eleme Element Operation Operation Operation
7
Refine Message Design for Quality
v0.1
v1.2 v1.3 v2.1
Pagination ?
Wish List Wish Template
Experimental Aggressive Two in
v1.1
API Service Level Pricing Plan Rate Limit Limited Version Semantic
Description Agreement Lifetime Identifier Versioning
Guarantee
APIs endpoints are identified and characterized by their roles in the overall system/
architecture at the early stages (inception). Next, operations are drafted with their
request and response message structure conceptualized and designed initially (elab-
oration). Quality improvements follow (construction). An approach to versioning
136 Chapter 4 Pattern Language Introduction
and a support/lifetime strategy is specified for APIs when they go live (transition);
updates are possible later on.
While Table 4.1 has an order from top to bottom (as all tables do), it can be
walked through multiple times, even within a single two-week sprint. We do not pro-
pose a waterfall model here; it is perfectly fine to go back and forth, for instance
when applying agile project organization practices. In other words, each sprint may
contain inception, elaboration, construction, and transition tasks (and apply related
patterns).
You might be wondering how the Align-Define-Design-Refine (ADDR) phases
(see introduction to Part 2) relate to the phases in the Unified Process and Table 4.1.
Our take is: Align corresponds to inception, the Define activities happen during
elaboration. Design work stretches from elaboration to construction iterations;
construction and transition (and later evolution and maintenance phases) provide
opportunities to Refine the design continuously.
Call to action: Which phase is your current API design effort in? Do the listed
patterns suggest being eligible for consideration in your design? You may want
to revisit Table 4.1 each time your design reaches a certain milestone or each time
you pick an API-related story from the product backlog at the start of a sprint.
Answering these two questions helps to scope and characterize an API and its
purpose: Frontend Integration and Backend Integration are two types of direc-
tions (or purpose and architectural position) of APIs. Public API, Community API,
and Solution-Internal API define API visibility. Figure 4.4 provides a pattern map
for these five patterns.
codify integration
Frontend Backend aspects of the API
Integration Integration
Pattern:
frontEnd intEgration
How can client-side end-user interfaces that are physically separated from
server-side business logic and data storage be populated and updated with
computing results, result sets from searches in data sources, and detailed
information about data entities? How can application frontends invoke activi-
ties in a backend or upload data to it?
Let the backend of a distributed application expose its services to
one or more application frontends via a message-based remote Frontend
Integration API.
The application frontends serving end users may be internal ones or be part of
external systems. Frontend Integration APIs are consumed by API clients in these
types of application frontends. Figure 4.5 positions the Frontend Integration
pattern in its context.
System A
User Interface
Frontend
API
Integration
Business Logic
Data Persistence
Figure 4.5 FRONTEND INTEGRATION: An API connects a remote user interface with backend
logic and data
Foundations: API Visibility and Integration Types 139
The Business Logic Layer [Fowler 2002] in the backend is a natural entry point.
Sometimes the user interface is also split up between client and server. In such cases,
the API might reside on the user interface level as well.
Details
Decide whether the API is a Public API, a Community API, or a Solution-
Internal API. Compose the request and, optionally, response messages of the API
operations from one or more Atomic Parameters and Parameter Trees (see later
sections for explanations of these patterns).
Realize the selected API endpoint candidates with the help of the role and respon-
sibility patterns (Chapter 5), the message structure patterns (Chapter 6), and the
quality patterns (Chapters 6 and 7). Consciously decide if and how to version the
integration API; consider one or more of our evolution patterns (Chapter 8, “Evolve
APIs”) when doing so. Document the API contract and the terms and conditions of
its use in an API Description and supplemental artifacts (Chapter 9).
A message-based remote Frontend Integration API is often realized as an
HTTP resource API.3 Other remoting technologies, such as gRPC [gRPC], trans-
ferred over HTTP/2 [Belshe 2015], or Web Sockets [Melnikov 2011], can also be used.
GraphQL has become popular recently, promising to avoid under- and overfetching.4
Frontend Integration APIs either have a general purpose that fits all clients or
specialize in providing different “Backends For Frontends” [Newman 2015] per type
of client or user interface technology.
Pattern:
baCkEnd intEgration
3. HTTP resource APIs use the uniform interface of the REST style and invoke HTTP methods such as
POST, GET, PUT, PATCH, and DELETE on URIs. If they adhere to additional constraints of REST,
such as using hyperlinks to transfer state, they may also be called RESTful HTTP APIs.
4. GraphQL can be seen as a large-scale framework realization of our Wish Template pattern from
Chapter 7.
140 Chapter 4 Pattern Language Introduction
How can distributed applications and their parts, which have been built inde-
pendently and are deployed separately, exchange data and trigger mutual
activity while preserving system-internal conceptual integrity without intro-
ducing undesired coupling?
Integrate the backend of a distributed application with one or more other
backends (of the same or other distributed applications) by exposing its ser-
vices via a message-based remote Backend Integration API.
Such Backend Integration APIs are never directly used by frontend clients of
the distributed application but are consumed by other backends exclusively.
Figure 4.6 positions the pattern in the first of its two application contexts, busi-
ness-to-business (or system-to-system) integration.
System A System B
Backend
Integration
Figure 4.7 illustrates the second usage context of the pattern, application-inter-
nal decomposition of business logic into service components exposing a Solution-
Internal API.
The entry to the business logic layer is a suitable location for a Backend Inte-
gration API. Access control, authorization enforcement, system transaction man-
agement, and business rule evaluation typically are already located here. In some
data-centric scenarios not requiring much logic, it may make sense to integrate on
the data persistence layer instead (this is not shown in Figure 4.7).
Foundations: API Visibility and Integration Types 141
Service-Oriented System
Backend
Integration
Data Persistence Data Persistence
Details
Decide on the visibility of the integration API: the options are Public API, Commu-
nity API, and Solution-Internal API. Compose the request and, optionally, response
messages of the API operations from one or more Atomic Parameters, possibly
nested in Parameter Trees (discussed further under “Basic Structure Patterns”).
Define the roles of the API endpoints in the Backend Integration and the responsi-
bilities of their operation (Chapter 5). Design the messages in detail with element
stereotypes and quality improvement patterns (Chapters 6 and 7). Consciously decide
if and how to version the integration API over its lifetime (Chapter 8) when doing so.
Create an API Description and supplemental information (Chapter 9).
Apply a systematic approach to application landscape planning (systems of sys-
tems design). Consider strategic domain-driven design (DDD) [Vernon 2013] as a
light approach to enterprise architecture management (“software city planning”). To
decompose a single system into services, apply cutting criteria derived from func-
tional requirements and domain model [Kapferer 2021, Gysel 2016] and operational
requirements such as scaling needs and developmental concerns such as independent
changeability [Zimmermann 2017]. Also, consider cloud cost and workload patterns
[Fehling 2014].
To promote interoperability, choose a mature remoting technology that supports
standard messaging protocols and established message exchange formats. In addition
to those listed as options to realize Frontend Integration, asynchronous, queue-
based messaging is often used in Backend Integrations (especially those integrating
separate systems); see discussion in Chapter 1 for rationale and examples.
142 Chapter 4 Pattern Language Introduction
Pattern:
PubLiC aPi
APIs exposed to the World Wide Web do not aim to limit their target audience and
accessibility but often control access to them with API Keys.
Mobile App
Third-Party
Systems
Details
Specify the API endpoints, operations, message representations, quality-of-service
guarantees, and life-cycle support model. Continue this integration design by choos-
ing responsibility patterns and choosing one or more evolution patterns (from Chap-
ters 5 and 8). For instance, mark the API as a Processing Resource, introduce
Version Identifiers, and apply Semantic Versioning.
Use API Keys (Chapter 7) or other security means to control access to the API.
Harden the API from a security and reliability perspective, and also invest in the qual-
ity of API Description and support procedures (Chapter 9). From an API economy
point of view, define a Pricing Plan and implement billing/subscription manage-
ment. Consider introducing Rate Limits for free plans. Document API usage terms
and conditions, for instance, in a Service Level Agreement, and let API consumers
Foundations: API Visibility and Integration Types 143
agree to them as a prerequisite to using the API. Cover fair use and indemnification
in these terms and conditions.5 These patterns are covered in Chapter 9.
Pattern:
COMMUNITY API
Some APIs are shared by clients in different organizations and might be deployed in
and accessible via networks available only to community members.
How can the visibility of and the access to an API be restricted to a closed
user group that does not work for a single organizational unit but for mul-
tiple legal entities (such as companies, nonprofit/nongovernment organiza-
tions, and governments)?
Deploy the API and its implementation resources securely in an access-restricted
location so that only the desired user group has access to it—for instance, in an
extranet. Share the API Description only with the restricted target audience.
Figure 4.9 sketches the Community API pattern in its architectural context.
End Users
(Extranet)
Web App
Community
API
Tenant Ops
Mobile App
Business Logic
Database
5. Being legally binding artifacts, terms and conditions documents and Service Level Agreements of Public
APIs should be written or at least reviewed and approved by professionals specializing in legal matters.
144 Chapter 4 Pattern Language Introduction
Details
Specify the API in terms of its endpoints, operations, message representations, qual-
ity of service guarantees, and life-cycle model. Refer to the solution details of Public
API for more comprehensive (equally valid) hints and related patterns.
Harden the API from a security and reliability perspective, and invest in the qual-
ity of API Description and support procedures (including community-managed
member support). Appoint a communitywide API owner and seek shared funding.
This pattern combines elements from its sibling visibility patterns Public API and
Solution-Internal API (and can be seen as a hybrid of these two patterns). For
instance, it may define a community-specific pricing model (in an approach similar
to that for a Public API), but also may consider colocation of API endpoints and
their implementations (as many Solution-Internal APIs do).
Pattern:
soLution-intErnaL aPi
Figure 4.10 sketches two instances of the Solution-Internal API pattern, sup-
porting an application frontend and another backend component, with sample API
clients and backend implementation.
Details
A collection of related Solution-Internal APIs sometimes is referred to as
Platform API. For instance, all Web APIs exposed in a single cloud provider offering
(or collections of such offerings) qualify as platform APIs; examples include APIs in
Amazon Web Services storage offerings and in Cloud Foundry. The same holds for
all Solution-Internal APIs within a software product such as a message-oriented
middleware; the endpoint and management APIs in ActiveMQ and RabbitMQ may
serve as examples of such platform APIs.
Foundations: API Visibility and Integration Types 145
Web App
Solution-Internal Solution-Internal
Frontend API Backend API
Mobile App
Business Logic 2
Database
Note that independent deployability does not have to imply independent deploy-
ment. A modular monolith [Mendonça 2021], for instance, uses plain messages
exchanging data transfer objects via local APIs; such a modular monolith can be
turned into a microservices-based system more easily than an object-oriented
“instance jungle” with tight couplings between the objects at runtime caused by call-
by-reference between remote methods and distributed garbage collection.
Designing and deploying Solution-Internal APIs for Backend Integration
to improve the coupling characteristics of applications and their parts is a complex
undertaking; both the first wave of service-oriented architectures in the 2000s and
the microservices trend that gained momentum since 2014 target this part of the
design space. Many books and articles exist, including some in this series [Vernon
2021]. We come back to the topic in Chapter 5.
rather common visualization of distributed systems (and their layers and tiers) that
places frontends at the top of figures/model diagrams and backends at the bottom; if
several systems are displayed, this is done along the x-axis of the figure. Note that a
left-to-right organization of such figures also is seen frequently.
You might be wondering why we call out the integration type and API visibil-
ity in pattern form; aren’t all these APIs just APIs with endpoints, operations, and
messages? They are. However, practical experience suggests that the business con-
texts and requirements for the two integration types are different; therefore, APIs
serving frontend and backend fulfill other purposes and are designed differently. For
instance, the protocol choice might differ in the two cases: HTTP often is a natural
(or the only) choice in Frontend Integration, while message queuing is attractive
in Backend Integration. The request and response message structures may vary
too in terms of their breadth and depth. An API that does both either makes design
compromises or has to offer optional features, which tends to complicate its usage.
Similar concerns apply to API visibility; for instance, a Public API often has more
advanced security requirements and stability needs than an internal one; the error
reporting has to consider that API clients and providers might not even know each
other (which is less likely for Solution-Internal APIs).
Next, we look at the building blocks of request and response messages, abstract-
ing from the data definition concepts in exchange formats such as JSON.
For instance, these design issues affect the resource URI (including path param-
eters), query, cookie, header parameters, and message content (also called message
body) when HTTP is the message exchange protocol. GET and DELETE requests
usually do not contain bodies, but responses to such requests do. HTTP POSTs,
PUTs, and PATCHes often contain both request and response bodies but may also
define one or more path, query, header, and cookie parameters. In a WSDL/SOAP
context, we can interpret this design issue as how the SOAP message parts should
be organized and which data types should be used to define the corresponding XML
schema elements. gRPC Protocol Buffers and GraphQL provide similar concepts to
specify messages, with similar granularity decisions required.
The four patterns in this section answer the two questions differently. An Atomic
Parameter describes plain data such as texts and numbers, and an Atomic Parame-
ter List groups several such elementary parameters. Parameter Trees provide nest-
ing (of atoms and other trees), and a Parameter Forest groups multiple such tree
parameters at the top level of a message. The pattern map in Figure 4.11 shows these
four patterns with their relations to each other.
Atomic Parameter
can be grouped to
Simple payload
is leaf of Atomic
is node of
Parameter List
is
Consumer node API Provider
of
Complex, nested
payload can be grouped to
Pattern:
atomiC ParamEtEr
Known from programming languages, basic types are the simplest unit of transmis-
sion in message exchanges between API clients and API providers (of all visibilities
and integration types introduced earlier in this section).
Decide whether the atom is single- or set-valued. Describe the meaning of the
transported values, at least informally, including, for instance, a unit of measure.
Consider specifying a value range to constrain the type of the Atomic Parameter.
Make this value-range information explicit—statically in the schema definition lan-
guage for the chosen message exchange format (for example, JSON Schema, Proto-
col Buffers, GraphQL Schema Language, or XML Schema) and/or dynamically in
runtime metadata.
Figure 4.12 visualizes a single-valued string parameter as a single instance of the
pattern appearing in a request message.
Data Transfer
Representation
Parameter
"ABC"
Figure 4.12 ATOMIC PARAMETER pattern: Single scalar (of basic type)
Basic Structure Patterns 149
In the Lakeside Mutual sample case, Atomic Parameters can be found in all API
operations, for instance, those dealing with services concerning customer informa-
tion. The first example is single-valued:
"city":Data<string>
Note that city is not the only Atomic Parameter in the example. The customer
identifier gktlipwhjr in the path of the URI also qualifies as such.
Atomic parameters may come as collections of basic types, which is expressed by
making the atom set-valued *, as shown in the following MDSL example:
"streetAddress":D<string>*
Atomic Parameters appear in all operation definitions and in their schema com-
ponents. Appendix B presents an OpenAPI specification from the Lakeside Mutual
case.
150 Chapter 4 Pattern Language Introduction
Details
Expressive names from the domain that the API belongs to make the API under-
standable for client developers and nontechnical stakeholders. Each atom might have
an exactly-one cardinality but also be optional (zero-or-one cardinality), set-valued
(at-least-one), or both (zero-or-more). Binary data might have to be encoded, for
instance, in Base64 [Josefsson 2006].
Note that the texts and numbers that travel in Atomic Parameters may actually be
structured internally, for instance, if a string has to match a certain regular expression
or is a collection of identically structured entries (such as the lines in the CSV format).
However, this structure is not something the API provider and the API client deal with
during serialization and deserialization. Preparing and processing valid data remains
a responsibility of the application containing the API client and the API implementa-
tion on the provider side. The API Description may define certain value range and
validation rules, but typically, the enforcement of these rules is not part of the interop-
erability contract but is an implementation-level task (as explained earlier). Note that
this “tunneling” approach is sometimes perceived as an antipattern because it bypasses
serialization/deserialization tools and middleware; this approach might appear to be
convenient, but it introduces technical risk and, possibly, security threats.
Atomic Parameters often play certain roles within a request or response mes-
sage. Chapter 6 highlights four such roles in the section on “Element Stereotypes”:
domain Data Element, Metadata Element, Id Element, and Link Element.
Pattern:
atomiC ParamEtEr List
Sometimes, a single Atomic Parameter is not expressive enough. Two or more such
Atomic Parameters might have strong semantic ties, or the content of a request or
response message might need several parts that are worth distinguishing from an API
client, API provider, or intermediary point of view.
The Atomic Parameter List as a whole, but also its elements, can be optional
or set-valued. These properties should be expressed as cardinalities in the API
Description.
Figure 4.13 sketches an application of the pattern in a request message. The data
transfer representation in the figure has three Atomic Parameter entries.
In the Lakeside Mutual case, an Atomic Parameter List may represent customer
addresses (MDSL notation):
{
"street": ["sampleStreetName"],
"postalCode": "42",
"city": "sampleCityName"
}
allows the API client to indicate that it wants the provider to include certain (but not
all) fields in the response:
The client does not identify the individual fields by a key but by position in the
GET request. The provider iterates through the list to decide whether or not to
include a field in the response. This, in fact, is the essence of an API quality pattern
called Wish List (presented in Chapter 7).
Details
Design advice for single Atomic Parameters is applicable here too; for instance, the
parameters should be named in a meaningful and consistent way; the chosen names
should be part of the domain vocabulary. The order of the atoms in the list should be
logical and express the proximity of the elements to improve human readability. The
API Description should provide representative examples for the permitted combi-
nations (instances of valid lists, that is).
Some platforms do not allow the communication participants to send multiple
scalars in a particular message type. For instance, many programming languages
allow only one return value or object in a response message; the default map-
pings from these languages to JSON and XML schema follow this convention (for
example, JAX-RS and JAX-WS in Java). The pattern cannot be used in that case; a
Parameter Tree has the required expressivity.
Pattern:
ParamEtEr trEE
Listing basic representation elements in a flat Atomic Parameter List that by defini-
tion contains only plain Atomic Parameters often is not sufficient, for instance,
when publishing rich domain data such as an order that contains order items or
products that are sold to many customers (that in turn buy many products).
Note that the pattern is defined recursively to yield the desired nested structures.
In HTTP APIs, nested JSON objects provide the tree structure expressed by this pat-
tern; set-valued tree nodes can be represented with JSON arrays containing JSON
objects corresponding to the nodes.
Figure 4.14 illustrates the pattern conceptually.
Figure 4.14 PARAMETER TREE pattern: Two versus one nesting level
In the Lakeside Mutual case, Parameter Trees can be found in several API opera-
tions that deal with customer and contract data. Picking up the example in Figure 4.1
at the beginning of this chapter, an example of a two-level nesting is as follows (note
that the AddressRecord in the example has already been defined as an Atomic
Parameter List above):
{
"customerId": "111",
"addressRecords": [{
"street": "somewhere1",
"postalCode": "42",
"city": "somewhere2"
}],
154 Chapter 4 Pattern Language Introduction
"moveHistory": [{
"from": {
"street": "somewhere3",
"postalCode": "44",
"city": "somewhere4"
},
"to": {
"street": "somewhere1",
"postalCode": "42",
"city": "somewhere2"
},
"when": "2022/01/01"
}]
}
Details
If the structure of the domain model element(s) represented as parameters is hierar-
chical or associative (with 1:1 relations such as customer overview and details or n:m
relations such as customers buying products), then using Parameter Tree is a natu-
ral choice that is beneficial for understandability compared to other options, such as
representing the complex structure in a flattened list. If additional data (such as secu-
rity information) has to be transmitted with the message, the hierarchical nature of a
Parameter Tree can set the additional data structurally apart from the domain
parameters and is thus well suited for this use case (Context Representation,
Chapter 6).
Parameter Trees are more complex to process than atoms, and bandwidth may
be wasted during message transfer if they contain unnecessary elements or an exces-
sive number of nesting levels. But if the structure that needs to be transferred is a deep
hierarchy, they typically are more efficient both in processing and bandwidth use
than sending multiple messages with simpler structures. Parameter Trees introduce
the risk that sometimes unnecessary information and/or more structure(s) informa-
tion is shared between API client and provider, for instance, when the optionality of
information is not defined explicitly. This might not be optimal with regard to for-
mat autonomy as a facet of loose coupling.
Note the recursive definition of the pattern. When applying the pattern, for
instance, when defining a JSON schema for the body of an HTTP POST request,
making use of such recursive definitions might be elegant (and sometimes cannot be
avoided); choices and optionality of nodes give tree construction processors a chance
6. https://microservice-api-patterns.github.io/MDSL-Specification/datacontract
Basic Structure Patterns 155
to terminate. However, even when doing so, such recursive definitions might also
lead to large message payloads that stress tools and runtime serializers such as Jack-
son (or even crash them).
Pattern:
ParamEtEr forEst
Just as Atomic Parameters may form Atomic Parameter Lists, Parameter Trees
can also be assembled into groups. This is useful only at the top level of a request or
response message header or payload.
Request Message
Data Transfer Representation
The Parameter Trees in the forest are accessed by position or name; in contrast to
trees that may contain other trees, Parameter Forests may not contain other forests.
The JSON rendering of this specification looks very similar to that of a tree of
the same structure:
"customers": [{
"customer": {
"customerId": "42",
"addressRecords": [{
"street": "someText",
"zipCode": "42",
"city": "someText"
}],
"moveHistory": []
}}],
"products": [{ "product": "someText" }]
}
However, a Java interface of the service unveils the slight difference in the opera-
tion signature:
Details
This pattern represents the special case of two or more nested top-level parameters
(or message body elements). In most technology mappings of the pattern, it is
semantically equivalent to a Parameter Tree with the forest members as the first
nesting level (see the JSON example presented earlier).
In HTTP resource APIs, the collection of query, path, cookie parameters, and
body jointly can be seen as such a forest (and is one of the reasons we have this
pattern).
Basic Structure Patterns 157
Flat Parameter Trees and Atomic Parameter Lists can be mapped to path
parameters or the query string of a URI, for instance, via “deepObject” serializa-
tion [OpenAPI 2022]. This gets more difficult or might even be impossible for deeply
nested trees; according to the OpenAPI Specification, the “behavior for nested
objects and arrays is undefined.”
All four types of basic structure elements can be used and combined to create
Metadata Elements, Id Elements, and Link Elements as variations of general-
purpose Data Elements (patterns from Chapter 6). Embedded Entities often come
as Parameter Trees, and Linked Information Holders use Atomic Parameter
Lists to define the link target (Chapter 7). A Version Identifier often is an Atomic
Parameter (Chapter 8).
Optionally, data provenance information can be provided in the API Descrip-
tion. Such information might include the entities, people, and processes involved in
producing the representation elements; the data origins; and where the data moves
over time. Note that such information may increase coupling because the message
receiver might start interpreting and depending on it, making the API harder to
change. The element stereotypes in Chapter 6 describe how to add this and other
semantic information to the representation elements: Metadata Element, Id Ele-
ment, and Link Element.
Chapter 3 covers the four basic structure patterns presented in this section with
their problem-solution pairs.
Summary
In this chapter, we established the scope of our pattern language, introduced its
organization, and discussed possible navigation paths. We also introduced five foun-
dation and four basic structure patterns not covered in depth later in the book.
The patterns capture proven solutions to design problems commonly encountered
when specifying, implementing, and maintaining message-based APIs. To ease navi-
gation, the patterns are grouped by life-cycle phase, scope, and category of design
concern. Each pattern in the following chapters is described following a common tem-
plate, progressing from context and problem to solution and example to discussion
and related patterns.
Summary 159
The basic building blocks of our pattern language were introduced in this chap-
ter, starting from Public API for Frontend Integration to Community API and
Solution-Internal API for Frontend Integration and Backend Integration to
flat and nested message structures including Atomic Parameters and Parameter
Trees.
Once it has been decided which type of API to build and where to expose it, end-
points and their operations can be identified. Assigning endpoint roles and opera-
tion responsibilities helps with that, which is the topic of Chapter 5. The message
and data contract design continues in Chapter 6. Linked Information Holder
and Embedded Entity are two more of the 44 patterns in this book. They served as
examples at the start of this chapter, and we return to them in Chapter 7.
This page intentionally left blank
Chapter 5
API design affects not only the structure of request and response messages, which we
covered in Chapter 4, “Pattern Language Introduction.” It is equally—or even
more—important to position the API endpoints and their operations within the
architecture of the distributed system under construction (the terms endpoints and
operations were introduced in the API domain model in Chapter 1, “Application Pro-
gramming Interface (API) Fundamentals”). If positioning is done without careful
thought, in a hurry, or not at all, the resulting API provider implementation is at risk
for being hard to scale and maintain when inconsistencies degrade conceptual integ-
rity; API client developers might find it difficult to learn and utilize the resulting
mishmash APIs.
The architectural patterns in this chapter play a central role in our pattern lan-
guage. Their purpose is to connect high-level endpoint identification activities with
detailed design of operations and message representations. We employ a role- and
responsibility-driven approach for this transition. Knowing about the technical roles
of API endpoints and the state management responsibilities of their operations
allows API designers to justify more detailed decisions later and also helps with run-
time API management (for instance, infrastructure capacity planning).
This chapter corresponds to the Define phase of the Align-Define-Design-Refine
(ADDR) process outlined in the introduction to Part 2 of the book. You do not have
to be familiar with ADDR to be able to apply its patterns.
161
162 Chapter 5 Define Endpoint Types and Operations
activities can ease the recovery from failures but also make it more difficult. For
example, APIs might provide compensating operations that undo work done
by previous calls to the same API; however, a lack of architectural clarity and
request coordination might also lead to inconsistent application state within
API clients and providers.
• Manageability: While one can design for runtime qualities such as performance,
scalability, and availability, only running the system will tell whether API design
and implementation are adequate. Monitoring the API and its exposed services
is instrumental in determining its adequacy and what can be done to resolve mis-
matches between stated requirements and observed performance, scalability, and
availability. Monitoring supports management disciplines such as fault, configu-
ration, accounting, performance, and security management.
• Consistency and atomicity: Business activities should have an all-or-nothing
semantics; once their execution is complete, the API provider finds itself in a
consistent state. However, the execution of the business activity may fail, or
clients may choose to explicitly abort or compensate it (here, compensation
refers to an application-level undo or other follow-up operation that resets the
provider-side application state to a valid state).
• Idempotence: Idempotence is another property that influences or even steers
the API design. An API operation is idempotent if multiple calls to it (with the
same input) return the same output and, for stateful operations, have the same
effect on the API state. Idempotence helps deal with communication errors by
allowing simple message retransmission.
• Auditability: Compliance with the business process model is ensured by audit
checks performed by risk management groups in enterprises. All APIs that
expose functionality that is subject to be audited must support such audits and
implement related controls so that it is possible to monitor business activities
execution with logs that cannot be tampered with. Satisfying audit require-
ments is a design concern but also influences service management at runtime
significantly. The article “Compliance by Design—Bridging the Chasm between
Auditors and IT Architects,” for instance, introduces “Completeness, Accuracy,
Validity, Restricted Access (CAVR)” compliance controls and suggests how to
realize such controls, for instance in service-oriented architectures [Julisch 2011].
in the books that we list in the preface). Here, we present patterns that carve out
important architectural characteristics of API endpoints and operations; doing so
simplifies and streamlines the application of these other tactics and patterns.
Some of the architectural questions an API design has to answer concern the input
to operations:
What can and should the API provider expect from the clients? For instance, what
are its preconditions regarding data validity and integrity? Does an operation
invocation imply state transfer?
What are the operation postconditions? What can the API client in turn expect
from the provider when it sends input that meets the preconditions? Does a
request update the provider state?
In an online shopping example, for instance, the order status might be updated
and can be obtained in subsequent API calls, with the order confirmation containing
all (and only) the purchased products.
Different types of APIs deal with these concerns differently. A key decision is
whether the endpoint should have activity- or data-oriented semantics. Hence, we
introduce two endpoint roles in this chapter. These types of endpoints correspond to
architectural roles as follows:
Data
Transfer
Resource
Processing Information
Resource Holder
Resource
?
Stored data characteristics
Responsibilities & constraints
A A’
(endpoint-level)
Mutable by Client
(operation-level)
no
A A’
Figure 5.1 Pattern map for this chapter (endpoint roles and operations responsibilities)
Endpoint Roles (aka Service Granularity) 167
Endpoint Roles
+ stateCreationOperation() + createInformationHolder()
+ retrievalOperation() + getInformationHolder()
+ stateTransitionOperation() + updateInformationHolder()
+ computationFunction() + deleteInformationHolder()
+ searchInformationHolder()
The two general endpoint roles are Processing Resource and Information
Holder Resource. They may expose different types of operations that write, read,
read-write, or only compute. There are five Information Holder Resource spe-
cializations, answering the following question differently:
How can data-oriented API endpoints be classified by data lifetime, link struc-
ture, and mutability characteristics?
Pattern:
ProCEssing rEsourCE
How can an API provider allow its remote clients to trigger actions in it?
How can clients ask an API endpoint to perform a function that represents a
business capability or a technical utility? How can an API provider expose the
capability of executing a command to its clients that computes some output
from the client’s input and, possibly, from the provider’s own state?
When invoking provider-side processing upon request from remote clients, gen-
eral design concerns are as follows:
also be defined. Not all of these properties have to be disclosed to API clients,
but they still must be described in the provider-internal API documentation.
API designers have to decide how much functionality each API endpoint and
its operations should expose. Many simple interactions give the client a lot of
control and can make the processing highly efficient, but they also introduce
coordination effort and evolution challenges; few rich API capabilities can pro-
mote qualities such as consistency but may not suit each client and therefore
may waste resources. The accuracy of the API Description matters as much as
that of its implementation.
• Learnability and manageability: An excessive number of API endpoints and
operations leads to orientation challenges for client programmers, testers, and
API maintenance and evolution staff (which might or might not include the
original developers); it becomes difficult to find and choose the ones appropri-
ate for a particular use case. The more options available, the more explana-
tions and decision-making support have to be given and maintained over time.
• Semantic interoperability: Syntactic interoperability is a technical concern for
middleware, protocol, and format designers. The communication parties must
also agree on the meaning and impact of the data exchanged before and after
any operation is executed.
• Response time: Having invoked the remote action, the client may block until
a result becomes available. The longer the client has to wait, the higher the
chances that something will break (either on the provider side or in client appli-
cations). The network connection between the client and the API may time out
sooner or later. An end user waiting for slow results may click refresh, thus
putting additional load on an API provider serving the end-user application.
• Security and privacy: If a full audit log of all API invocations and resulting
server-side processing has to be maintained (for instance, because of data
privacy requirements), statelessness on the provider side is an illusion even if
application state is not required from a functional requirement point of view.
Personal sensitive information and/or otherwise classified information (for
example, by governments or enterprises) might be contained in the request and
response message representations. Furthermore, in many scenarios one has to
ensure that only authorized clients can invoke certain actions (that is, com-
mands, conversation parts); for instance, regular employees are usually not
permitted to increase their own salary in the employee management systems
integrated via Community APIs and implemented as microservices. Hence, the
security architecture design has to take the requirements of processing-centric
170 Chapter 5 Define Endpoint Types and Operations
API operations into account—for instance in its policy decision point (PDP)
and policy enforcement point (PEP) design and when deciding between role-
based access control (RBAC) and attribute-based access control (ABAC). The
processing resource is the subject of API security design [Yalon 2019] but also
is an opportunity to place PEPs into the overall control flow. The threat model
and controls created by security consultants, risk managers, and auditors also
must take processing-specific attacks into account, for instance denial-of-
service (DoS) attacks [Julisch 2011].
• Compatibility and evolvability: The provider and the client should agree on
the assumptions concerning the input/output representations as well as the
semantics of the function to be performed. The client expectations should
match what is offered by the provider. The request and response message
structures may change over time. If, for instance, units of measure change or
optional parameters are introduced, the client must have a chance to notice
this and react to it (for instance, by developing an adapter or by evolving itself
into a new version, possibly using a new version of an API operation). Ideally,
new versions are forward and backward compatible with existing API clients.
These concerns conflict with each other. For instance, the richer and the more
expressive a contract is, the more has to be learned, managed, and tested (with regard
to interoperability). Finer-grained services might be easier to protect and evolve, but
there will be many of them, which have to be integrated. This adds performance
overhead and may raise consistency issues [Neri 2020].
A “Shared Database” [Hohpe 2003] that offers actions and commands in the
form of stored procedures could be a valid integration approach (and is used in prac-
tice), but it creates a single point of failure, does not scale with a growing number
of clients, and cannot be deployed or redeployed independently. Shared Databases
containing business logic in stored procedures do not align well with service design
principles such as single responsibility and loose coupling.
How It Works
For the new endpoint, define one or more operations, each of which takes over
a dedicated processing responsibility (“action required”). Computation Function,
State Creation Operation, and State Transition Operation are common in
activity-oriented Processing Resources. Retrieval Operations mostly are lim-
ited to mere status/state checks here and are more commonly found in data-oriented
Information Holder Resources. For each of these operations, define a “Com-
mand Message” for the request. Add a “Document Message” for the response when
realizing an operation as a “Request-Reply” message exchange [Hohpe 2003]. Make
the endpoint remotely accessible for one or more API clients by providing a unique
logical address (for instance, a Uniform Resource Identifier [URI] in HTTP APIs).
Figure 5.3 sketches this endpoint-operation design in a UML class diagram.
Endpoint Roles
API
Processing Resource
+ preconditions
+ invariants
+ postconditions
- resourceState // here: processInstanceState
+ stateCreationOperation(in): ResponseMessage1
+ retrievalOperation(in): ResponseMessage2
+ stateTransitionOperation(in): ResponseMessage3
+ computationFunction(in): ResponseMessage4
Resource State
ProcessingResourceImpl
+ createUpdateDelete(Data)
- applicationState
+ lookupById(key): Value
+ retrieve(query): Set<Data> + processOperation(in): ResponseMessageN
Figure 5.3 PROCESSING RESOURCES represent activity-oriented API designs. Some operations
in the endpoint access and change application state, others do not. Data is exposed only in
request and response messages
172 Chapter 5 Define Endpoint Types and Operations
The request message should make the performed action explicit and allow the API
endpoint to determine which processing logic to execute. These actions might repre-
sent a general-purpose or an application-domain-specific functional system capabil-
ity (implemented within the API provider or residing in some backend and accessed
via an outbound port/adapter) or a technical utility.
The request and response messages possibly can be structured according to any of
the four structural representation patterns Atomic Parameter, Atomic Parameter
List, Parameter Tree, and Parameter Forest. The API Description has to docu-
ment the syntax and semantics of the Processing Resource (including operation
pre- and postconditions as well as invariants).
The Processing Resource can be a “Stateful Component” or a “Stateless Com-
ponent” [Fehling 2014]. If invocations of its operations cause changes in the (shared)
provider-side state, the approach to data management must be designed deliberately;
required decisions include strict vs. weak/eventual consistency, optimistic vs. pes-
simistic locking, and so on. The data management policies should not be exposed
in the API (which would make them visible to the API client), but open and close
(or commit, rollback) system transactions be placed inside the API implementation,
preferably at the operation boundary. Application-level compensating operations
should be offered to handle things that cannot be undone easily by system transac-
tion managers. For instance, an email that is sent in an API implementation cannot
be taken back once it has left the mail server; a second mail, “Please ignore the previ-
ous mail,” has to be sent instead [Zimmermann 2007; Richardson 2018].
Example
The Policy Management backend of the Lakeside Mutual case contains a stateful
Processing Resource InsuranceQuoteRequestCoordinator that offers State
Transition Operations, which move an insurance quotation request through vari-
ous stages. The resource is implemented as an HTTP resource API in Java and Spring
Boot:
@RestController
@RequestMapping("/insurance-quote-requests")
public class InsuranceQuoteRequestCoordinator {
@Operation(
summary = "Updates the status of an existing " +
"Insurance Quote Request")
@PreAuthorize("isAuthenticated()")
@PatchMapping(value = "/{id}")
public ResponseEntity<InsuranceQuoteRequestDto>
respondToInsuranceQuote(
Endpoint Roles (aka Service Granularity) 173
Authentication,
@Parameter(description = "the insurance quote " +
"request's unique id", required = true)
@PathVariable Long id,
@Parameter(description = "the response that " +
"contains the customer's decision whether " +
"to accept or reject an insurance quote",
required = true)
@Valid @RequestBody
InsuranceQuoteResponseDto insuranceQuoteResponseDto) {
@RestController
@RequestMapping("/riskfactor")
public class RiskComputationService {
@Operation(
summary = "Computes the customer's risk factor.")
@PostMapping(
value = "/compute")
public ResponseEntity<RiskFactorResponseDto>
computeRiskFactor(
@Parameter(description = "the request containing " +
"relevant customer attributes (e.g., birthday)",
required = true)
@Valid @RequestBody
RiskFactorRequestDto riskFactorRequest) {
Discussion
Business activity- and process-orientation can reduce coupling and promote infor-
mation hiding. However, instances of this pattern must make sure not to come across
as remote procedure call (RPC) tunneled in a message-based API (and consequently
174 Chapter 5 Define Endpoint Types and Operations
be criticized because RPCs increase coupling, for instance, in the time and format
autonomy dimensions). Many enterprise applications and information systems do
have “business RPC” semantics, as they execute a business command or transaction
from a user that must be triggered, performed, and terminated somehow. According
to the original literature and subsequent collections of design advice [Allamaraju
2010], an HTTP resource does not have to model data (or only data), but can repre-
sent such business transactions, long-running ones in particular.1 Note that “REST
was never about CRUD” [Higginbotham 2018]. The evolution of Processing
Resources is covered in Chapter 8.
A Processing Resource can be identified when applying a service identification
technique such as dynamic process analysis or event storming [Pautasso 2017a];
this has a positive effect on the “business alignment” tenet in service-oriented
architectures. One can define one instance of the pattern per backend integration
need becoming evident in a use case or user story; if a single execute operation is
included in a Processing Resource endpoint, it may accept self-describing action
request messages and return self-contained result documents. All operations in the
API have to be protected as mandated by the security requirements.
In many integration scenarios, activity- and process-orientation would have to be
forced into the design, which makes it hard to explain and maintain (among other
negative consequences). In such cases, Information Holder Resource is a better
choice. It is possible to define API endpoints that are both processing- and data-
oriented (just like many classes in object-oriented programming combine stor-
age and behavior). Even a mere Processing Resource may have to hold state (but
will want to hide its structure from the API clients). Such joint use of Processing
Resource and Information Holder Resource is not recommended for microser-