APIs serve a specific role within an API-led approach — unlocking data from systems, composing data into processes, or delivering an experience. If the whole organization commits to this approach everyone in the business is empowered to access their best capabilities in delivering applications and projects through discovery, self-service, and reuse.
However, according to Gartner, about 50% of managed APIs will support event-driven IT by 2020. Event-driven APIs will be part of a technology mix helping an organization achieve a competitive advantage with real-time integration. For that reason organizations — not only in the beginning of defining their integration strategy — regularly ask us two common questions:
- Should we leverage an event-driven architecture or API-led approach?
- Is there a hybrid between event-driven and API-led connectivity?
In this blog post, we will discuss the differences between events and APIs, discuss the differences between an event-driven architecture and API-led connectivity, how they can work together, and how it will benefit your business.
Events vs. APIs
Events and APIs can be compared and contrasted along the following dimensions:
- Programmatic: Both are primarily programmatic communication approaches in nature, i.e. intended for communication between application components.
- Meaning: An event describes a state change that has occured in an application component which acts as the event producer, whereas an API is a programmatic interface to a service provided by the application component exposing that API.
- Dynamic nature: An event describes something that has already happened, whereas an API describes an action that is going to be performed once the API invocation is received.
- Static nature: Events denoting state changes of the same kind of the same event type. This is the equivalent of the API and specifically the API data model used in the API specification.
- Granularity: An event type is typically for one well-defined state change, whereas an API invocation can expose many resources and support many HTTP methods per resource. Thus, an API is more akin to a group of event types than a single event type.
- Synchronicity: API invocations are by definition synchronous, consisting of request and synchronous response, even though the processing triggered by an API invocation can be performed asynchronously. Thus, if API client and API implementation are not both available throughout the duration of the API invocation then it fails. In contrast, events are exchanged asynchronously — therefore the event producer and consumer are decoupled in time.
- Communication path: An API invocation is from one API client to one API implementation, and the API client specifically addresses the API implementation. Events are sent by an event producer to a destination (queue, topic, message exchange — depending on messaging paradigm) and are then received by event consumers from that destination. Without the producer and consumers being each other. Furthermore, there can be more than one consumer for each event.
- Broker: Exchanging events requires a message broker, such as Anypoint MQ, Kafka, ActiveMQ, or RabbitMQ — just to name a few. Those act as the owner of destinations, whereas API invocations, at a minimum, only require API client and API implementation.
- Contract: The contract for an API is its API specification — ideally a RAML definition. The contract for an event is the combination of destination and event (data) type and can be described by an AsyncAPI definition.
Now that we understand the differences between events and APIs, we can start comparing event-driven architecture and API-led connectivity.
Event-driven architecture vs. API-led connectivity
MuleSoft defines API-led connectivity through the lens of a three-tiered approach. These three layers are made up of experience APIs, process APIs and system APIs.
Although application components exchanging events can be organized similarly — this is not an inherent part of an event-driven architecture.
API-led connectivity restricts communication patterns according to the three tiers (essentially top to bottom), whereas application components exchanging events do not have to adhere to the same communication pattern restrictions.
API implementations typically have well-defined static dependencies on other APIs or backend systems. While similar relationships may materialize in an event-driven architecture at runtime, there are no static dependencies between the application components exchanging events. Instead, these application components only depend on the exchanged event types, the destinations and the message broker hosting those destinations. Furthermore, event consumers may change dynamically at any time, thereby dynamically reconfiguring the relationship graph of the application components in an event-driven architecture, without the event producers becoming aware of that change.
An event-driven architecture requires a message broker as an additional component of the technology architecture, with all application components which exchange events having to agree on the same message broker.
API-led connectivity (and in particular application networks) are defined by the API-centric assets published for self-service consumption. The equivalent for an event-driven architecture would revolve around destination and event types.
Can an event-driven architecture and API-led connectivity work together?
Let’s look into a few scenarios driving the need for elements from event-driven architecture.
- Integration with modern SaaS applications: They heavily depend on approaches from an event-driven architecture to ensure high availability and scalability (e.g. event-driven architecture on the Salesforce Customer 360 Platform).
- Internet of Things: The huge volume of events streamed from devices need to be accessible in real-time and at scale which makes synchronous request-response APIs alone unreasonable.
- Fault-tolerance: A system is listening for notifications when transactions or orders in an eCommerce system have been canceled or failed.
- Avoid polling: Processing notifications (e.g. an order has been updated), decide what action to take, and route the appropriate response to a backend system instead of constantly polling for changes.
- Legacy systems: They need to process the notifications but suffer from reliability issues.
In our following example, we will have a mobile app that lets customers create, change, and view their customer data and orders.
User journey 1: Cancelling an order
At the experience layer, we have a mobile API listening for relevant notifications when our customer is interacting with our mobile app via Webhooks, publish-subscribe, or a similar mechanism — like cancelling an order. In this scenario, the mobile API validates and transforms the message using DataWeave, before publishing it onto the relevant queue — in this case, the orders queue. This queue may be implemented as Anypoint MQ, Kafka, ActiveMQ, RabbitMQ, or any other message broker.
At the process layer, a Mule application consumes the messages from the orders queue. This Mule application essentially acts as an event handler and inspects the message’s header and payload to determine the relevant course of action by using the ‘choice router’ scope.
The event handler will decide which process or system APIs to invoke when an order gets cancelled so the message from the original event gets transmitted to the right backend systems. In this example, only the orders backend system needs to be updated. Hence the event handler application will only invoke the orders system API, which exposes the relevant endpoint for updating or cancelling an order and passes the message in the required format.
User journey 2: Updating customer profile
In this example, where our customer updates personal data in their mobile app, we are using the same experience API. The experience API will publish the message into the queue — but this time the customers queue. Just like in the previous example, our event handler will consume the messages from our customers queue and based on the message header and payload decide which underlying process or systems APIs to invoke. As we are now trying to update the customer’s data, the event handler invokes the customers process API which then calls the underlying system APIs for updating the data in Salesforce and SAP.
User journey 3: Getting order details
In our last example, our customer has got home and wants to get details about their recent orders. Similar to the other examples we use an experience API to handle the request. As our customer is using a web app instead of the mobile app, we will now use the new web app experience API.
Rather than publishing the message into a queue, we are following the typical API-led approach, where the experience API invokes the process APIs, and the process APIs invoke the system APIs. Our web app experience API might not provide us with the orders backend system-specific customer Id, which is required to get all related orders of a customer. For that reason, we have the order history process API sitting in between the experience layer and system layer. The order history process API will first call the customer process API to find out the customer ID, ie: get the customer Id by providing Salesforce and SAP with the name of the customer. Once the customer process API has successfully received the customer ID, it will then pass it to the order history API in order to invoke the orders system API — providing it with the required customer ID.
In case one of the backend systems is not available or unable to persist in the data, there are different approaches to handle the unhappy path. For example, putting the message back to the queue for reprocessing, moving the message to the dead letter queue, acknowledging the experience API about the error message and how to proceed, or simply triggering any other manual or automatic process.
What are the benefits of combining an event-driven architecture with API-led-connectivity?
With a combined approach you can reuse process and system APIs for future use cases without having to rewrite transformation logic and connectivity to backend systems. On top of that, you can use messaging queues to ensure zero message loss, increase the reliability and robustness of your IT applications, and add another tool in the toolbox covering the situations where synchronous request-response APIs might not be optimal.
This post uses content found in the Anypoint Platform Architecture: Application Networks course. If you want to learn more about how to successfully combine event-driven architecture and API-led connectivity, sign up for the course.