Specification: Ballerina Messaging Library
Owners: @TharmiganK @shafreenAnfar @daneshk @ThisaruGuruge
Reviewers: @daneshk @ThisaruGuruge @shafreenAnfar
Created: 2025/07/16
Updated: 2025/07/16
Edition: Swan Lake
Introduction
This is the specification for the Messaging standard library of Ballerina language, which provides a unified, extensible API for message persistence and consumption in Ballerina applications. It abstracts the underlying message store technology, enabling developers to interact with various message brokers or databases through a consistent interface. This approach simplifies integration, fosters code consistency, and supports advanced messaging patterns such as retries and dead-letter queues (DLQs).
The Messaging library specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant GitHub tag.
If you have any feedback or suggestions about the library, start a discussion via a
GitHub issue or in the
Discord server. Based on the outcome of the discussion, the specification and
implementation can be updated. Community feedback is always welcome. Any proposal, which affects the
specification can be found in the Ballerina Specification repository
under stdlibs/proposals/messaging
.
The conforming implementation of the specification is released to Ballerina central. Any deviation from the specification is considered a bug.
Contents
- Overview
- Message Store Interface
- Store Listener
- Message Store Service
- In-Memory Message Store
- Example Usage
- Extensibility
1. Overview
This module defines a set of interfaces and implementations for message storage and consumption. The key components are:
- Message Store Interface: Defines the contract for storing, retrieving, and acknowledging messages.
- Store Listener: Polls a message store at configurable intervals and dispatches messages to an attached service, with support for retries and DLQs.
- Message Store Service: A service object that processes messages delivered by the listener.
- In-Memory Message Store: A default implementation for testing and lightweight use cases.
2. Message Store Interface
The Store
interface is the core abstraction for message persistence. It defines the following operations:
store(anydata message)
: Persists a message.retrieve()
: Retrieves the next available message for processing.acknowledge(string id, boolean success = true)
: Acknowledges the outcome of message processing.
Message Structure:
type Message record {| readonly string id; anydata payload; |};
Store Interface:
type Store isolated client object { isolated remote function store(anydata message) returns error?; isolated remote function retrieve() returns Message|error?; isolated remote function acknowledge(string id, boolean success = true) returns error?; };
3. Store Listener
The StoreListener
class orchestrates message consumption from a Store
implementation. It polls the store at a
configurable interval, dispatches messages to an attached service, and manages retries and DLQ handling.
Configuration:
type StoreListenerConfiguration record {| decimal pollingInterval = 1; int maxRetries = 3; decimal retryInterval = 1; boolean ackWithFailureAfterMaxRetries = true; Store deadLetterStore?; |};
Key Features:
- Configurable polling, retry, and DLQ behavior
- Attachable service for message processing
- Graceful and immediate stop operations
4. Message Store Service
A StoreService
is a service object that processes messages delivered by the listener. It must implement the following
method:
type StoreService distinct isolated service object { isolated remote function onMessage(anydata message) returns error?; };
If onMessage
returns an error, the listener will retry processing according to the configuration. After exhausting
retries, the message can be dropped or moved to a DLQ.
5. In-Memory Message Store
The InMemoryMessageStore
is a built-in implementation of the Store
interface. It is suitable for testing and
lightweight scenarios where persistence is not required.
6. Example Usage
import ballerina/messaging; messaging:Store msgStore = new messaging:InMemoryMessageStore(); listener messaging:StoreListener msgStoreListener = new(msgStore, { pollingInterval: 10, maxRetries: 2, retryInterval: 2 }); service on msgStoreListener { isolated remote function onMessage(anydata payload) returns error? { // Process the message } }
7. Extensibility
Developers can implement the Store
interface to integrate with custom message brokers or databases. The listener and
service patterns remain unchanged, ensuring consistent application logic regardless of the underlying store technology.
public isolated client class CustomStore { *messaging:Store; isolated remote function store(anydata message) returns error? { // Custom implementation to store the message } isolated remote function retrieve() returns Message|error? { // Custom implementation to retrieve a message } isolated remote function acknowledge(string id, boolean success = true) returns error? { // Custom implementation to acknowledge a message } }