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 holds data. Two application instances connect to a cluster of three members as clients, each keeping a near cache of hot entries. The data is split into partitions, 271 by default. Each member owns the primary copy of some partitions and holds the backup copy of partitions owned by another member, so losing one member loses no data. Underneath, the database stays the system of record; the cluster reads missing entries from it and writes changes back through MapStore.HOW A HAZELCAST CLUSTER HOLDS YOUR DATAApp instance 1Spring Boot, clientnear cacheApp instance 2Spring Boot, clientnear cacheHazelcast cluster271 partitions by defaultMember 1PRIMARYP0P3P6BACKUPP2P5P8and moreMember 2PRIMARYP1P4P7BACKUPP0P3P6and moreMember 3PRIMARYP2P5P8BACKUPP1P4P7and moreMapStore: load and write backDatabase, still the system of record
Partitions P0 to P8 stand for the 271 a cluster has by default. Primary copies are solid, backups dashed. Source for the defaults: Hazelcast data partitioning.

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 getAll and putAll, 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.

AreaPracticeWhy it mattersOn Community Edition
SizingPlan memory for the data times (1 + backup count), plus room for one member to failAfter a failure the survivors hold everythingSame
TopologyClient-server for production services; embedded for one small serviceApplication and grid scale and restart separatelySame
DiscoveryTurn off multicast; use Kubernetes or cloud discovery, or a fixed member listMembers find each other reliably, and only each otherSame
Network securityPrivate network, firewall rules for the member ports (5701 and up), TLS and role-based accessThe grid holds production data in clear formTLS and RBAC are Enterprise; rely on network isolation
Data limitsSet eviction, a size limit and an expiry on every cache mapUnbounded maps end in long GC pauses and failuresSame
SerializationCompact serialization with explicit serializers; no java.io.SerializableSmaller payloads, faster reads, safe schema changesSame
Near cacheUse it for read-mostly maps, with invalidation on change and a size limitHot reads skip the networkSame
MonitoringRun Management Center and export metrics to your existing monitoring; alert on heap, partition migrations and client connectionsProblems show before users noticeManagement Center's free mode covers clusters of up to 3 members
UpgradesRolling upgrades or blue/green, rehearsed on staging; test serialization changesNo downtime, no unreadable dataPlan a maintenance window or switch clusters at the application
RecoveryPersistence or WAN replication, with a tested restoreA full-cluster outage does not mean a cold startReload 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.