Skip to content

Hazelcast Migration

LoomCache is not a Hazelcast member implementation and it does not accept Hazelcast clients. Treat the migration as a client API, configuration, and operations change: replace the dependency, map each data structure to a LoomCache facade, and test failure behavior under Raft replication.

  1. Inventory Hazelcast APIs in use: data structures, SQL, CP primitives, Spring Cache, MapStore, discovery, security, and management endpoints.
  2. Replace the client bootstrap and connect to explicit LoomCache seeds.
  3. Migrate one data structure at a time, keeping object names stable where possible.
  4. Run shadow reads or dual writes for critical maps.
  5. Rehearse member restart, leader failover, and snapshot restore with production-like data.

Replace the Hazelcast client bootstrap with the LoomClient builder and explicit seeds:

LoomClient client = LoomClient.builder()
.addSeed("loomcache-node1.eu-west.prod.lan:7654")
.addSeed("loomcache-node2.eu-west.prod.lan:7654")
.addSeed("loomcache-node3.eu-west.prod.lan:7654")
.tlsConfig(tlsConfig)
.credentialsFactory(new StaticCredentialsFactory(ClientCredentials.certificate()))
.build();
client.connect();
// Production map values can use documented scalar, binary, or registered-object encodings.
LoomMap<String, String> customers = client.getMap("customers");

Spring applications can use loom-spring-boot for the LoomCache client facade, LoomCacheManager, REST controllers, Spring Session, actuator health, and optional embedded server beans.

Hazelcast APILoomCache APINotes
IMap<K,V>LoomMap<K,V>Get, put, putAll, putIfAbsent, delete, scan, getAll, listeners, near cache, stats, SQL helpers, and selected atomic map operations. Also loadAll (MapLoader-style warm-up; non-sharded maps), getEntryView (entry metadata), putTransient (in-memory + Raft replicated, no MapStore write-through), evict(key) (Raft-applied single-key eviction, distinct from the unsupported background eviction policy), removeAll(LoomQuery) (two-step query-then-delete, not one atomic mutation), and LoomQuery/LoomPredicate predicate queries. executeOnKey/executeOnKeys/executeOnEntries entry processors are allowlist-gated (see Gotchas).
ReplicatedMap<K,V>LoomReplicatedMap<K,V>AP, eventually-consistent broadcast map (put, get, remove, containsKey, size) with per-key last-writer-wins and a background anti-entropy sweep; not linearizable. Writes fail closed under loomcache.profile=production until broadcast convergence is chaos-certified (-Dloomcache.replicatedmap.allow-production=true opts in for non-production use); reads are unrestricted.
Spring CacheLoomCacheManagerCache names map to LoomCache map names.
IQueue<E>LoomQueue<E>Client facade supports offer, poll, peek, size, drain, bulk offer, bounded bulk poll/drain, blocking take() and timed poll(Duration) (client-side long-poll), and async variants. QueueStore snapshot/restart parity is not production-supported yet.
ISet<E>LoomSet<E>Add, remove, contains, size, clear, cursor scan, iterable scanner, and async variants. There is no bulk members() fetch; use scanner() to iterate.
ITopic<E>LoomTopic<E>Publish/subscribe over the current client-managed polling path; do not assume Hazelcast-style push dispatch semantics.
ReliableTopic<E>LoomReliableTopic<E>Ringbuffer-backed replay; validate retention settings.
MultiMap<K,V>LoomMultiMap<K,V>Dedicated client facade and REST controller.
IList<E>LoomList<E>Dedicated client facade and REST controller.
Ringbuffer<E>LoomRingbuffer<E>Dedicated client facade; embedded persistence uses RingbufferStore.
FlakeIdGeneratorLoomIdGeneratorSnowflake-style IDs; verify bit-layout assumptions.
PNCounter, GSet, ORSet, LWWRegisterLoomPNCounter, LoomGSet, LoomORSet, LoomLWWRegisterCRDT facades for AP-style state, not linearizable coordination.
FencedLockLoomLinearizableLockProduction lock calls use a Raft-managed CP session created and heartbeated by the Java client; direct session management is not a public application workflow.
ISemaphore, IAtomicLongLoomLinearizableSemaphore, LoomAtomicLong (via consistencySubsystem())Atomic long, lock, and Java-client-managed semaphore calls are the production-supported CP surface. LoomLinearizableSemaphore uses a Raft-managed CP session created and heartbeated by the Java client; sessionless semaphore mutations fail closed. Other CP extension handles are non-production only and their direct requests are rejected under loomcache.profile=production.
Hazelcast SQLLoomCache SQLMap-scoped SELECT support exists. CREATE INDEX and declarative SQL indexes are unsupported/rejected in this release. No Jet job model.
Predicate, PredicateBuilderLoomQuery, LoomPredicateProgrammatic predicate DSL (eq/ne/gt/ge/lt/le/between/in/like/regex/and/or/not, orderBy, limit) compiled to map-scoped SELECT and executed via LoomMap.keySet/entrySet/values/project/count and aggregations. JSON, Map, and record values expose their fields as queryable columns.
QueryCache (continuous query)LoomQueryCache<K,V>Continuously-maintained filtered view via LoomQueryCache.create(...) (client-side predicate) or createServerFiltered(...) (server-side SerializablePredicate); batching, coalescing, and buffering through LoomQueryCacheConfig / loomcache.client.query-cache.*.
MapStore / MapLoaderNo drop-in production equivalentPackaged generic JDBC MapStore declarations remain production fail-closed. The Spring default-map JPA bridge is not installed in production, although unsafe/local optional datasources are rejected when the bean is present. Custom MapStore use in production must be wired through a clustered server extension so leader-owned writes, snapshot/graceful-drain recovery for write-behind queues, and the leader-owned read-through fill path are active. Use write-through for data that must reach the external store before failover.
Management CenterJMX, Prometheus, Grafana; REST only for non-production operator opt-insLoomCache has no Management Center equivalent. Production blocks direct REST data/admin and direct data-structure management reads; use MXBeans, Prometheus metrics, Grafana dashboards, and alert rules for production operations.
Hazelcast conceptLoomCache equivalent
Member port 5701Direct JVM/default ClusterConfig member port is 5701; the Docker samples expose the member service on 7654.
backup-count / async-backup-countRaft majority replication; no async backup count knob.
Partition count271 smart-routing partitions by default plus the server migration-slot table.
In-memory formatTagged scalar/binary payloads or registered Kryo object envelopes; no OBJECT or NATIVE toggle.
Serialization configExplicit Kryo IDs, Compact serializers, GenericRecord, or the global serializer SPI. There is no Hazelcast-like implicit POJO object mode.
Kubernetes discoveryUse explicit static seeds rendered by your deployment tooling; LoomCache does not query Kubernetes or cloud discovery APIs at runtime.
TLS / mTLSConfigure loomcache.tls.* keystore, truststore, and client-auth settings (LoomProperties binds exclusively under the loomcache prefix). Plan certificate rotation as a rolling restart.
  • LoomMap.executeOnKey (entry processor) is production-gated by EntryProcessorAllowlist. Under the production profile, only explicitly allowlisted fully-qualified class names (set via the JVM property loomcache.entryprocessor.allowlist) are accepted; all others are rejected before deserialization. Hazelcast users accustomed to unrestricted entry processors must register each processor class name before migrating.
  • Synthetic/computed query attributes (Hazelcast ValueExtractor) are available server-side via registerValueExtractor, gated by a deny-all loomcache.query.extractor.allowlist. Once an extractor’s fully-qualified class name is allowlisted, its attribute is queryable like any stored field.
  • Hazelcast clients and XML/YAML config files are not wire-compatible with LoomCache.
  • Writes acknowledge after Raft majority commit, so latency and minority-partition behavior differ.
  • Reads are linearizable by default; local backup reads exist only for non-production embedded/member-local compatibility testing, may be stale, and are rejected by the production profile.
  • SQL targets maps only. There is no Jet pipeline, CDC connector suite, or multi-language client set.
  • Kryo class IDs must be stable and identical across clients and members before data is written.
  • Registered LoomMap<K,V> POJO keys/values use the client Kryo object envelope; unregistered POJOs fail closed, and server-side SQL/index paths do not introspect object envelopes as Hazelcast OBJECT format.
  • Production sharding is unsupported/fail-closed until per-group WAL, snapshot, install-snapshot, restart recovery, durable migration chunk ACKs, and consensus-backed ownership cutover are release-gated; validate on the default single replicated Raft group unless the release notes say otherwise.
  • Server-side LRU, LFU, finite max-entry/max-memory eviction, and max-idle are unsupported for production parity until eviction decisions are Raft-applied and proven through WAL/snapshot/restart tests.
  • There is no off-heap/NATIVE memory tier.
  • Map every Hazelcast object name to a LoomCache object name and facade.
  • Port client bootstrap, TLS, auth, and serializer registration.
  • Restore a staging snapshot with production-like serialized classes.
  • Compare counts, sampled reads, SQL results, TTL behavior, listener events, and any approved non-production external-persistence effects.
  • Run restart, leader-failover, network-partition, and restore drills.
  • Enable Prometheus scraping, import Grafana dashboards, and load the alert rules.
  • Freeze Hazelcast writes, replay the final delta, switch clients to LoomCache seeds, and retain rollback data.

This guide is the public operator-oriented migration checklist for the release.

LoomCache is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Hazelcast, Inc. or by any other company whose products are named in this documentation. “Hazelcast” is a trademark of Hazelcast, Inc.; references to it are nominative and describe only migration and comparison. All other product and company names are trademarks of their respective owners and are used for identification purposes only.