sapui5tutors SAPUI5 • Fiori • SAP BTP Step-by-step tutorials Real project examples Interview Q&A
Practical SAPUI5 • Fiori • SAP BTP tutorials and interview prep

SAP Event Mesh: Publish and Subscribe Basics

Why polling is a habit worth breaking

Here's a pattern every SAP developer has written: a job that wakes up every 10 minutes, asks S/4HANA "anything new?", and goes back to sleep. It works. It's also wasteful, laggy, and scales badly.

Events flip that around. The source system announces "a sales order was created" the moment it happens, and interested apps react immediately. SAP Event Mesh is the BTP service that moves those messages around — publish and subscribe, decoupled and asynchronous.

Polling asks "anything new?" on a timer. Events tell you the instant something happened. Once a system grows past a handful of integrations, that difference decides your architecture.


The core vocabulary

Three concepts cover 90% of Event Mesh:

  • Topic — a named channel, like sap/s4/beh/salesorder/v1/created. Publishers send to topics; subscribers listen on them.
  • Queue — a subscriber's private inbox. Messages wait here until the subscriber reads them, so nothing is lost if your app restarts.
  • Message — the payload, usually JSON with a CloudEvents envelope describing what happened and when.

The beautiful part: the publisher doesn't know who subscribes. S/4HANA fires "order created" and doesn't care whether zero or ten apps are listening. Adding a new consumer never touches the sender.


Publishing: S/4HANA fires the event

Say you need your BTP app notified whenever a sales order is created. In S/4HANA, you enable the relevant business event (for example via the Enterprise Event Enablement setup), and configure Event Mesh as the channel. From then on, every new sales order produces a message on its topic.

From a custom app, publishing is just an HTTP POST (AMQP is supported too) to the messaging endpoint with the topic in the path and the payload in the body:

POST /messaging/v1/topics/sap/custom/order/events
{
  "specversion": "1.0",
  "type": "com.mycompany.order.created",
  "source": "/btp/cap/order-service",
  "data": { "orderId": "487", "netValue": 12500 }
}

Design your topics like a public API. Clear names, stable payload shapes, versioned paths — future you will be grateful when a second team starts consuming.


Subscribing: your app listens

On the consuming side, you create a queue and subscribe it to the topic in the Event Mesh dashboard. Then your app connects and reads:

  1. Connect to the messaging service (credentials come from the service binding / service key).
  2. Read messages from your queue.
  3. Acknowledge each message after processing — unacknowledged messages get redelivered.

A CAP Node.js service can consume via the @sap/xb-msg-amqp-v100 client; a Java service uses the messaging client from the SAP Cloud SDK. The pattern is the same: long-lived connection, process, acknowledge.

One practical tip: make your handlers idempotent. At-least-once delivery means the same message can arrive twice. If your handler updates a database, guard with a check on the event ID.


When events beat OData (and when they don't)

Use events when you need near-real-time reactions — order created, delivery posted, invoice approved — across decoupled systems. Use OData calls when you need an immediate answer: "give me this order's current status" is a query, not an event.

Most real architectures use both: events announce that something changed, and the consumer calls OData to fetch the fresh details. The event is the tap on the shoulder; OData is the conversation.

Events notify, OData answers. A healthy integration uses the event as a trigger and a targeted API call to get exactly the data it needs.

Questions? Drop them in the comments.