A pricing page takes 800 ms because every request asks the same database for the same few thousand rates, and each database server you add helps less than the last.
What Hazelcast is used for, above all, is ending that wait: it keeps the hot data in memory, spread across your application servers, so reads skip the database and capacity grows by adding machines.
What is Hazelcast?
Hazelcast is an in-memory data grid written in Java: software that pools the memory of several servers into one store your application reads and writes like a map. Each server running Hazelcast is a member, and together the members form a cluster. Data lives in RAM, so a lookup takes microseconds inside the cluster and around a millisecond across the network, instead of a database query and its disk.
The current release line is Hazelcast Platform 5.7, released in May 2026 (release history), and it is the first to support Java 25 (what is new in 5.7).
How a Hazelcast cluster stores data
Hazelcast hashes every key to one of 271 partitions by default and spreads the partitions evenly across the members. One member owns the primary copy of each partition, and another holds a backup. When a member joins or leaves, the cluster moves partitions until the load is even again, and when one fails, the backups take over (Hazelcast documentation).
Your code never sees this. It calls map.get(key), and the client sends the call straight to the member that owns the key.
Embedded or client-server
Hazelcast runs in two topologies. Embedded: every application instance is also a cluster member, which is the simplest setup and the fastest for reads, but couples the cache's memory and lifecycle to the application's. Client-server: the cluster runs as its own service and applications connect as clients, so each side scales and restarts on its own schedule. Most production systems we see use client-server, with a near cache on the client for the hottest keys.
Community Edition and Enterprise Edition
Hazelcast comes in two editions (editions and distributions). The Community Edition is free under the Apache License 2.0 and the Hazelcast Community License, and covers the distributed data structures, caching with MapStore, distributed compute, stream processing and the Spring integration.
The 5.7 feature table marks a long list as Enterprise only, and several of them were free in older releases: CP data structures such as FencedLock and IAtomicLong, SQL querying, TLS encryption, role-based access control, WAN replication, persistence, rolling upgrades, the High-Density Memory Store and patch releases with security fixes. Community releases are the x.y.0 versions on Maven Central; the patch releases after them ship to Enterprise customers. Check the edition before you design around a feature, especially when you are upgrading from an old 3.x or 4.x cluster.
What is Hazelcast used for? Five ways it speeds up applications
The common thread is the same: Hazelcast pays off when many servers need the same data quickly and the database has become the queue they all wait in.
1. A shared cache in front of a slow database
The most common use. Reference data, prices, product details and the results of expensive queries sit in a Hazelcast map, and every application instance reads the same copy. Unlike a cache inside each instance, a new instance starts warm and an update is visible everywhere at once. For the business that means pages that stay fast at peak traffic and a database sized for writes rather than for every read.
2. Fast shared state for pricing, availability and sessions
Some data changes all day and is read far more often than it is written: hotel availability, stock levels, exchange rates, user sessions. Holding it in the grid gives every server a consistent, current view without a round trip to the database for each request, and a server can fail without logging users out.
3. Computing next to the data
Instead of pulling an entry over the network, changing it and writing it back, you send the change to the member that owns the key with an entry processor. The update runs where the data is, in one step, with no lock to manage. Aggregations and queries can run on all members in parallel in the same way.
4. Absorbing traffic spikes
A grid turns a spike of reads into memory lookups and can queue writes for the database with write-behind. A ticket sale, a marketing campaign or the end of a trading day lands on the cluster, which you scale by adding members, while the database keeps a steady load.
5. Processing event streams
Hazelcast's Jet engine runs stream processing pipelines inside the cluster: reading from Kafka or a database change stream, joining events with data already in memory and writing results back to maps. Fraud checks, real-time dashboards and price recalculations are typical jobs.
When is Hazelcast the wrong tool? A single application instance is better served by an in-process cache such as Caffeine, with no network hop at all. If all you need is a shared key-value cache for services in several languages, a managed Redis service may be simpler to run. Our guide to improving Java performance covers where each kind of cache fits.
Integrating Hazelcast with Spring Boot, step by step
Spring Boot auto-configures Hazelcast: if Hazelcast is on the class path and it finds a configuration, it creates a HazelcastInstance you can inject (Spring Boot reference). Hazelcast 5.7 supports Spring Framework 7.0, 6.2 and 5.3 (Hazelcast Spring integration). The steps below build a price cache for a Spring Boot 4 service, first as an embedded cluster for development, then as a client of a separate cluster for production.
Step 1: Add the dependencies
Spring Boot 4 has a starter for Hazelcast. Its dependency management still pins Hazelcast 5.5.0 (managed versions), so set the version property to move to 5.7. The hazelcast-spring module is what lets Spring's caching abstraction use Hazelcast (Spring Boot caching).
<properties>
<java.version>25</java.version>
<hazelcast.version>5.7.0</hazelcast.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hazelcast</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
With Gradle and the Spring dependency management plugin, the same thing looks like this:
ext['hazelcast.version'] = '5.7.0'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-hazelcast'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'com.hazelcast:hazelcast-spring'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
Step 2: Configure the cluster and the map
Put a hazelcast.yaml at the root of the class path, where Spring Boot looks for it by default. This configuration names the cluster, turns off multicast discovery (which most cloud networks block anyway) and gives the prices map a backup, an expiry policy and a size limit.
hazelcast:
cluster-name: pricing
network:
join:
auto-detection:
enabled: false
multicast:
enabled: false
tcp-ip:
enabled: true
member-list:
- 127.0.0.1
map:
prices:
backup-count: 1 # one synchronous backup on another member
time-to-live-seconds: 300 # an entry expires 5 minutes after it was written
max-idle-seconds: 120 # or after 2 minutes without a read
eviction:
eviction-policy: LRU
max-size-policy: PER_NODE
size: 200000 # entries per member, a hard memory bound
serialization:
compact-serialization:
serializers:
- serializer: com.example.pricing.PriceSerializer
Every cache map needs a size limit and an expiry. Without them, the map grows until the members run out of heap, and the first symptom is long garbage collection pauses across the whole cluster.
Step 3: Define the data and its serializer
Everything stored in Hazelcast crosses the network in serialized form, so the format matters for speed and size. Compact serialization is the current default choice (Hazelcast documentation): it works with Java records without any configuration, supports adding and removing fields, and lets queries read single fields without deserializing the whole object. Hazelcast does not recommend the zero-configuration mode for performance-critical code, because it relies on reflection, so write an explicit serializer for hot types:
public record Price(String sku, String currency, long amountMinor, long updatedAtMillis) {}
public class PriceSerializer implements CompactSerializer<Price> {
@Override
public Price read(CompactReader reader) {
return new Price(
reader.readString("sku"),
reader.readString("currency"),
reader.readInt64("amountMinor"),
reader.readInt64("updatedAtMillis"));
}
@Override
public void write(CompactWriter writer, Price price) {
writer.writeString("sku", price.sku());
writer.writeString("currency", price.currency());
writer.writeInt64("amountMinor", price.amountMinor());
writer.writeInt64("updatedAtMillis", price.updatedAtMillis());
}
@Override
public Class<Price> getCompactClass() {
return Price.class;
}
@Override
public String getTypeName() {
return "price";
}
}
Avoid java.io.Serializable for cached types. It is slow, produces large payloads and ties the stored data to the exact class version.
Step 4: Cache method results with Spring's annotations
Enable caching and tell Spring Boot to use Hazelcast explicitly. Hazelcast also implements JCache, and Spring Boot tries JCache providers first, so setting the type avoids surprises. Each cache name maps to a Hazelcast map with the same name, which is how the prices settings from step 2 apply.
# application.yaml
spring:
cache:
type: hazelcast
@Configuration
@EnableCaching
class CacheConfig {
}
@Service
public class PriceService {
private final PriceRepository repository;
public PriceService(PriceRepository repository) {
this.repository = repository;
}
@Cacheable(cacheNames = "prices", key = "#sku + ':' + #currency")
public Price price(String sku, String currency) {
return repository.load(sku, currency); // runs only on a cache miss
}
@CacheEvict(cacheNames = "prices", key = "#price.sku() + ':' + #price.currency()")
public void update(Price price) {
repository.save(price); // the next read reloads the new value
}
}
Step 5: Work with the map directly where it pays
The annotations cover read-through caching. For shared state that changes, inject the HazelcastInstance and use the map's own operations. An entry processor runs on the member that owns the key, and Hazelcast processes the entries of one partition one at a time, so this stock reservation needs no lock and makes one network call:
@Component
public class StockReservations {
private final IMap<String, Integer> stock;
public StockReservations(HazelcastInstance hazelcast) {
this.stock = hazelcast.getMap("stock");
}
public boolean reserve(String sku, int quantity) {
return stock.executeOnKey(sku, entry -> {
Integer available = entry.getValue();
if (available == null || available < quantity) {
return false;
}
entry.setValue(available - quantity); // runs where the data lives
return true;
});
}
}
In client-server mode the entry processor's class has to be available on the members as well, so keep processors small and in a module you deploy to both.
Step 6: Connect to a separate cluster in production
For production, run the members as their own service, for example a StatefulSet in Kubernetes with Kubernetes discovery switched on in the members' configuration, and turn the application into a client. Spring Boot creates a client instead of a member when it finds a hazelcast-client.yaml on the class path. The near cache keeps the hottest prices inside the application and drops an entry as soon as it changes in the cluster:
hazelcast-client:
cluster-name: pricing
network:
cluster-members:
- hz-0.hz.pricing.svc.cluster.local:5701
- hz-1.hz.pricing.svc.cluster.local:5701
- hz-2.hz.pricing.svc.cluster.local:5701
near-cache:
prices:
in-memory-format: OBJECT
invalidate-on-change: true
time-to-live-seconds: 60
eviction:
eviction-policy: LRU
max-size-policy: ENTRY_COUNT
size: 50000
serialization:
compact-serialization:
serializers:
- serializer: com.example.pricing.PriceSerializer
Move the map settings from step 2 (backups, expiry, eviction) to the members' hazelcast.yaml; on the client they have no effect.
Step 7: Check that it works
Start two instances of the application in embedded mode. The log of each should show a member list of size two once they find each other. With Actuator on the class path, Spring Boot adds a HazelcastHealthIndicator to the health endpoint (Actuator endpoints), so your existing health checks report the grid:
curl -s localhost:8080/actuator/health | jq '.components.hazelcast'
Then load-test the endpoint with the cache cold and warm. The hit rate and the drop in database queries are the numbers that justify running a cluster at all.
Building scalable applications with Hazelcast
Clustering for high availability
Members check each other's health continuously. When one stops responding, its partitions are promoted from the backups on the surviving members and new backups are created, with no action from the application. Two settings decide how much you can lose:
- Backup count. One synchronous backup, the default, survives the loss of one member at a time. Critical maps can have two; asynchronous backups trade a small window of risk for faster writes.
- Split-brain protection. If a network failure splits the cluster, each half keeps serving. A minimum cluster size per map stops a small half from accepting writes that would conflict later.
Size the cluster so that the survivors can hold all the data, primaries and backups, after the largest failure you plan for. A three-member cluster that is 80% full will not survive losing a member.
Improving application performance
Most of the speed comes from a handful of decisions rather than from tuning flags:
- Read hot keys from a near cache, and accept the short staleness its invalidation allows.
- Send work to the data with entry processors and aggregations, instead of moving data to the work.
- Batch with
getAllandputAll, which group keys by the member that owns them. - Keep values small and use Compact serialization with explicit serializers.
- Load the grid from the system of record in bulk at startup, then keep it current from a change stream, rather than filling it one cache miss at a time.
Advanced Hazelcast features
Beyond maps and caching, Hazelcast 5.7 offers the following. The edition column of the 5.7 feature table is noted for each.
- Jet stream processing (both editions): pipelines over Kafka, files and change data capture, running inside the cluster.
- CP Subsystem (Enterprise): strongly consistent locks, counters and maps built on the Raft consensus algorithm, for leader election and coordination.
- High-Density Memory Store (Enterprise): keeps data off the Java heap, so large data sets do not lengthen garbage collection pauses.
- WAN replication (Enterprise): keeps clusters in different regions in sync for disaster recovery and local reads.
- Persistence (Enterprise, formerly Hot Restart): writes the in-memory state to disk so a restarted cluster recovers its data quickly.
- Rolling upgrades and blue/green deployments (Enterprise): new versions without downtime.
- SQL (Enterprise): standard SQL over maps, Kafka topics and files.
- Thread-Per-Core engine (Enterprise): an alternative networking model for higher throughput per member.
- Vector collections (Enterprise, beta): similarity search over embeddings, for AI retrieval.
Best practices for Hazelcast and Management Center deployment
The table collects the decisions we check first on any Hazelcast cluster, ours or one we inherit. Where a practice depends on an Enterprise feature, the last column says what to do on the Community Edition.
| Area | Practice | Why it matters | On Community Edition |
|---|---|---|---|
| Sizing | Plan memory for the data times (1 + backup count), plus room for one member to fail | After a failure the survivors hold everything | Same |
| Topology | Client-server for production services; embedded for one small service | Application and grid scale and restart separately | Same |
| Discovery | Turn off multicast; use Kubernetes or cloud discovery, or a fixed member list | Members find each other reliably, and only each other | Same |
| Network security | Private network, firewall rules for the member ports (5701 and up), TLS and role-based access | The grid holds production data in clear form | TLS and RBAC are Enterprise; rely on network isolation |
| Data limits | Set eviction, a size limit and an expiry on every cache map | Unbounded maps end in long GC pauses and failures | Same |
| Serialization | Compact serialization with explicit serializers; no java.io.Serializable | Smaller payloads, faster reads, safe schema changes | Same |
| Near cache | Use it for read-mostly maps, with invalidation on change and a size limit | Hot reads skip the network | Same |
| Monitoring | Run Management Center and export metrics to your existing monitoring; alert on heap, partition migrations and client connections | Problems show before users notice | Management Center's free mode covers clusters of up to 3 members |
| Upgrades | Rolling upgrades or blue/green, rehearsed on staging; test serialization changes | No downtime, no unreadable data | Plan a maintenance window or switch clusters at the application |
| Recovery | Persistence or WAN replication, with a tested restore | A full-cluster outage does not mean a cold start | Reload from the system of record; measure how long it takes |
Management Center is the cluster's console: dashboards for members, clients and maps, a configuration health check, a Prometheus exporter and administration tasks (Management Center documentation). Run it as its own small deployment, not on a member, put it behind your single sign-on, and keep it on the same network segment as the cluster so its port is never exposed publicly.
Hazelcast and in-memory data grids at Stratoflow
We have built and tuned Java systems on in-memory data grids since 2013, with Hazelcast, Oracle Coherence or Apache Ignite depending on the system and the license the client already holds.
For a major UK hotel bookings aggregator we moved availability search from a cluster of SQL Server machines into an in-memory data grid that holds everything a search needs, loaded in bulk and kept current by a message stream. The engine now serves 300 million queries a day, with response times down 60% and infrastructure cost down 80% (case study). FastPost, the accounting platform we developed for Legerity, processes a billion financial transactions in under an hour on an in-memory engine and a distributed grid (case study).
If a database has become the ceiling for your application's speed or cost, our performance engineering team starts by measuring where the time goes, then tells you in writing whether a grid is the fix or an expensive detour.