In today’s microservices and real-time data architectures, messaging systems play a critical role in decoupling services, improving responsiveness, and enabling event-driven design. While Kafka has been the go-to tool for many, Apache Pulsar is emerging as a powerful alternative, offering multi-tenancy, geo-replication, and true queue + stream semantics.

This post shows how to integrate Apache Pulsar with Spring Boot, covering producers, consumers, topics, and key best practices for building scalable messaging systems.


Why Choose Apache Pulsar?

Apache Pulsar is a distributed messaging and streaming platform with some key differentiators:

  • Separation of storage and compute
  • Multi-tenancy with authentication and authorization
  • Geo-replication out of the box
  • Support for both streaming (pub-sub) and queue (exclusive/failover) patterns
  • Built-in schema registry

These features make Pulsar suitable for both simple event queues and large-scale data pipelines.


Setting Up the Environment

You can run a standalone Pulsar cluster using Docker:

docker run -it -p 6650:6650 -p 8080:8080 apachepulsar/pulsar:3.1.0 bin/pulsar standalone
  • Broker Port: 6650
  • Admin HTTP Port: 8080

Access the admin console: http://localhost:8080


Adding Dependencies to Spring Boot

Spring has native support for Pulsar via the Spring for Apache Pulsar project.

Add the following dependencies in pom.xml:

<dependency>
<groupId>org.springframework.pulsar</groupId>
<artifactId>spring-pulsar-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

Configuration in application.yml

Configure the broker service URL and other client settings:

spring:
pulsar:
client:
service-url: pulsar://localhost:6650
producer:
topic-name: my-topic
consumer:
topic-names: my-topic
subscription-name: my-subscription
subscription-type: exclusive

Creating a Pulsar Producer

You can auto-wire a PulsarTemplate to send messages:

@Service
public class NotificationProducer {

    private final PulsarTemplate<String> pulsarTemplate;

    public NotificationProducer(PulsarTemplate<String> pulsarTemplate) {
        this.pulsarTemplate = pulsarTemplate;
    }

    public void send(String message) {
        pulsarTemplate.send("notifications", message);
    }
}

Pulsar supports multiple serialization formats like JSON, Avro, and Protobuf.


Consuming Messages from a Topic

Use the @PulsarListener annotation to consume messages:

@Component
public class NotificationConsumer {

    @PulsarListener(subscriptionName = "notification-sub", topics = "notifications")
    public void receive(String message) {
        System.out.println("Received: " + message);
    }
}

Subscription types:

  • Exclusive (only one consumer)
  • Shared (multiple consumers share load)
  • Failover (primary/backup)
  • Key_Shared (hashing per key)

Using POJOs and JSON Schema

Pulsar supports schema evolution. You can send Java objects instead of raw strings:

public class Order {
private String id;
private double amount;
}
pulsarTemplate.newMessage(Order.class)
.withTopic("orders")
.withValue(new Order("123", 500.0))
.send();

Configure the listener:

@PulsarListener(topics = "orders", subscriptionName = "order-sub")
public void handleOrder(Order order) {
System.out.println("Order received: " + order.getId());
}

Scaling Consumers and Partitioned Topics

To scale consumers, use partitioned topics:

bin/pulsar-admin topics create-partitioned-topic persistent://public/default/my-topic -p 3

In Spring:

spring:
pulsar:
consumer:
subscription-type: shared

Each consumer instance receives a subset of messages, enabling parallelism.


Error Handling and Retries

Use @PulsarListener error handling options:

@PulsarListener(topics = "errors", subscriptionName = "err-sub")
public void onError(String msg) {
try {
process(msg);
} catch (Exception ex) {
throw new PulsarListenerException("Failed to process", ex);
}
}

Configure retries and dead-letter topics in YAML:

spring:
pulsar:
consumer:
dead-letter-policy:
max-redeliver-count: 3
dead-letter-topic: errors-DLQ

Monitoring and Metrics

Monitor your Pulsar cluster with:

  • Pulsar Manager UI
  • Prometheus + Grafana
  • pulsar-admin CLI tool

Expose metrics from Spring Boot using Micrometer and integrate them with Prometheus.


Conclusion

Apache Pulsar + Spring Boot provides a powerful platform for building scalable, event-driven, and resilient messaging systems. With native support for schemas, partitioned topics, and flexible subscription models, Pulsar addresses the limitations of traditional brokers.

Whether you’re modernizing monoliths, building microservices, or designing IoT/event-processing pipelines, Pulsar’s architecture gives you the tools to build systems that scale.