Skip to content

Serialization Policy

LoomCache uses Kryo as the default object serializer and requires every serialized runtime class to be registered. Compact serialization, GenericRecord, and the global serializer SPI are available for schema-oriented or custom formats, but default map values, snapshots, and protocol payloads still depend on a stable serializer contract.

LoomMap<K,V> generics are a Java client convenience, not Hazelcast-style implicit object mode. In this release, the public map wire path is limited to the supported scalar and binary value encodings; arbitrary POJO map values are not production-supported. Treat Compact / GenericRecord / global serializer APIs as future or internal payload mechanisms for maps until the public client, member apply path, WAL replay, and snapshot restore all use that contract end to end.

  • Register application classes before clients write data or members load snapshots/WAL records.
  • Use the same class, numeric ID, and optional custom serializer on every client and member that can read or write the payload.
  • Treat IDs as durable schema identifiers. Never recycle an ID for a different class.
  • Keep a version-controlled registry and allocate IDs monotonically.
  • Register classes explicitly in a fixed startup path; do not depend on scan order.
  • Roll out new registrations everywhere before writing values that need them.
  • Prove each production value type through client round-trip, WAL replay, snapshot restore, restart, and mixed-version tests before relying on it for bank data.

KryoSerializer reserves IDs 10-38 for LoomCache base/JDK registrations, including the intentionally skipped ID 37. Application IDs should start at 1000.

  1. Null sentinel.
  2. Application class-specific serializer from registerClass(clazz, id, serializer).
  3. Application class registration from registerClass(clazz, id).
  4. LoomCache base registrations.
  5. Fail closed for unknown classes.

Application serializers cannot override LoomCache base registrations. Duplicate class IDs and duplicate class registrations are rejected.

LoomClient client = LoomClient.builder()
.addSeed("127.0.0.1:5701")
.registerClass(Customer.class, 1000)
.registerClass(Order.class, 1001, new OrderKryoSerializer())
.build();
client.connect();

LoomClient.registerClass(...) is also available after construction. Use it only before the client serializes or deserializes values of that class.

Server members must install the same registry before they accept writes or replay durable state. This applies to embedded members, standalone server bootstraps, entry processors, executor payloads, CP atomic references, snapshots, and WAL replay. MapStore values are non-production only in this release because production profiles fully disable/fail-close MapStore.

For Spring deployments, centralize the registry in configuration code shared by all services that start a LoomClient or embedded server. For container deployments, bake the registration module into the server image and roll every member before enabling writes that use new classes.

Use Compact serialization when schema evolution matters more than raw Kryo class IDs. Compact payloads carry a type name, field metadata, and a stable fingerprint so readers can tolerate extra fields and provide defaults for missing fields. GenericRecord lets tooling read or create Compact payloads without loading the application class.

Compact still has a compatibility contract: type names, field names, field kinds, and custom compact serializers must be deployed consistently.

GlobalSerializerRegistry loads Kryo by default, or the highest-priority LoomSerializerProvider from ServiceLoader. Applications may replace the process-wide serializer directly for tests or custom deployments. A custom global serializer becomes part of the wire and snapshot compatibility contract.

The root SERIALIZATION.md includes the longer operator checklist.