DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Failure Handling Mechanisms in Microservices and Their Importance
  • Chaos Engineering for Microservices
  • Mastering Scalability in Spring Boot
  • gRPC and Its Role in Microservices Communication

Trending

  • Unlocking AI Coding Assistants Part 2: Generating Code
  • Java’s Next Act: Native Speed for a Cloud-Native World
  • A Guide to Developing Large Language Models Part 1: Pretraining
  • It’s Not About Control — It’s About Collaboration Between Architecture and Security
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring WebFlux: publishOn vs subscribeOn for Improving Microservices Performance

Spring WebFlux: publishOn vs subscribeOn for Improving Microservices Performance

This article explains the benefits of using PublishOn and SubscribeOn Reactor operators for improving microservices performance.

By 
Bablu Lal user avatar
Bablu Lal
·
Sep. 23, 24 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
7.9K Views

Join the DZone community and get the full member experience.

Join For Free

With the rise of microservices architecture, there has been a rapid acceleration in the modernization of legacy platforms, leveraging cloud infrastructure to deliver highly scalable, low-latency, and more responsive services.

Why Use Spring WebFlux?

Traditional blocking architectures often struggle to keep up performance, especially under high load. Being Spring Boot developers, we know that Spring WebFlux, introduced as part of Spring 5, offers a reactive, non-blocking programming model designed to address these challenges.

WebFlux leverages event-driven, non-blocking, asynchronous processing to maximize resource efficiency, making it particularly well-suited for I/O-intensive tasks such as database access, API calls, and streaming data.

About This Article

Adopting Spring WebFlux can significantly enhance the performance of the Spring Boot applications. Under normal load, Spring Boot WebFlux applications perform excellently, but for the scenarios where the source of the data is blocking, such as I/O-bound, the default (main) IO thread pool can cause contention if downstream responses are very slow and degrade the performance. In this article, I will try to cover how publishOn and subscribeOn reactor operators can come to the rescue.

Understanding publishOn and subscribeOn

(Note: I have used the Schedulers.boundedElastic() scheduler as a more scalable reactive thread pool group.  Spring Boot WebFlux provides other schedulers that can be used based on need.)

publishOn(Schedulers.boundedElastic()) and subscribeOn(Schedulers.boundedElastic()) are used by Reactor to control where certain parts of the reactive pipeline are executed, specifically on a different thread or thread pool. However, the two operators serve different purposes:

1. publishOn(Schedulers.boundedElastic())

Purpose

This switches the downstream execution to the specified scheduler, meaning that any operators that come after the publishOn will be executed on the provided scheduler (in this case, boundedElastic).

Use Case

If you want to switch the execution thread for all the operators after a certain point in your reactive chain (for example, to handle blocking I/O or expensive computations), publishOn is the operator to use.

Example

Java
 
Mono.fromSupplier(() -> expensiveBlockingOperation())
    .publishOn(Schedulers.boundedElastic()) // Switch downstream to boundedElastic threads
    .map(result -> process(result))
    .subscribe();


When To Use publishOn

  • Use when you need to run only the downstream operations on a specific scheduler, but want to keep the upstream on the default (or another) scheduler.
  • It is useful for separating the concerns of upstream and downstream processing, especially if upstream operators are non-blocking and you want to handle blocking operations later in the pipeline.

2. subscribeOn(Schedulers.boundedElastic())

Purpose

This changes the thread where the subscription (upstream) occurs. It moves the entire chain of operators (from subscription to completion) to the provided scheduler, meaning all the work (including upstream and downstream operators) will run on the specified scheduler.

Use Case

Use this if you need to run the entire chain (both upstream and downstream) on a specific thread pool or scheduler, such as for blocking I/O tasks or when you want to handle the subscription (data fetching, database calls, etc.) on a different thread.

Example

Java
 
Mono.fromSupplier(() -> expensiveBlockingOperation())
    .subscribeOn(Schedulers.boundedElastic()) // Runs the entire chain on boundedElastic threads
    .map(result -> process(result))
    .subscribe();


When To Use subscribeOn

  • Use when you want to run the entire pipeline (upstream + downstream) on the boundedElastic scheduler.
  • It's particularly useful for situations where the source of the data is blocking, such as I/O-bound operations (reading from disk, network calls, database queries, etc.), and you want to move everything off the default event loop thread (if using Netty or Reactor Netty).

Differences Between publishOn and subscribeOn 

  • publishOn affects only the downstream operations from the point where it is called. If placed in the middle of a chain, everything after the publishOn will be scheduled on the provided scheduler, but everything before it will stay on the previous scheduler.
  • subscribeOn affects the entire reactive chain, both upstream and downstream. It's often used to move blocking upstream operations (like I/O) to a non-blocking thread pool.

Choosing Between the Two

  • Use publishOn(Schedulers.boundedElastic())if:
    • You need fine-grained control over where specific parts of the reactive chain run.
    • You want to switch only the downstream operations (after a certain point) to a specific scheduler.
    • Example: You're performing non-blocking reactive operations first, and then want to handle blocking operations downstream in a different thread pool.
  • Use subscribeOn(Schedulers.boundedElastic())if:
    • You want to run the entire reactive chain (from the point of subscription onward) on a different scheduler.
    • The source operation (like a network call or database query) is blocking, and you want to move the blocking subscription and all subsequent operations to a specific scheduler like boundedElastic.
  • In short:
    • If you have blocking code upstream (like a blocking I/O source), use subscribeOn.
    • If you want to isolate downstream blocking work (e.g., after some non-blocking calls), use publishOn.

Common Use Case: Blocking I/O in Reactive Programming

If you're working with I/O-bound operations (like file reads, database queries, etc.), and you want to offload blocking operations to a bounded thread pool, here's how you might use these:

Database Call or a Blocking I/O Call

Java
 
Mono.fromCallable(() -> performBlockingDatabaseCall())
    .subscribeOn(Schedulers.boundedElastic()) // Offload blocking database call to boundedElastic
    .map(result -> process(result))            // Further processing
    .subscribe();


Here, the subscribeOn ensures that the entire pipeline, including the blocking I/O, runs on the boundedElastic scheduler.

Mixed Non-Blocking and Blocking Operations

Java
 
Mono.just("Initial value")
    .map(value -> transformNonBlocking(value)) // Non-blocking operation
    .publishOn(Schedulers.boundedElastic())    // Switch thread for blocking operation
    .flatMap(value -> Mono.fromCallable(() -> performBlockingOperation(value))) // Blocking operation
    .subscribe();


In this case, the publishOn ensures that only the downstream blocking work (i.e., the flatMap) is moved to a different scheduler, while the earlier non-blocking operations stay on the default one.

Summary

  • subscribeOn affects the entire reactive chain and is typically used when the source operation (like database access) is blocking.
  • publishOn switches the scheduler for all operations downstream from where it is called and is better when you want to run only certain parts of the chain on a different thread.
Thread pool Operator (extension) microservices Performance Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • Failure Handling Mechanisms in Microservices and Their Importance
  • Chaos Engineering for Microservices
  • Mastering Scalability in Spring Boot
  • gRPC and Its Role in Microservices Communication

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!