Tracking, updating documents
Fluxzero allows you to track changes to your document store using the @HandleDocument annotation.
This enables handlers to react to document updates in real time — much like handling events.
@HandleDocumentvoid handle(UserAccount user) { log.info("UserAccount {} was added or updated", user.getUserId());}@HandleDocumentfun handle(user: UserAccount) { log.info("UserAccount ${user.userId} was added or updated")}How it works
Section titled “How it works”Every time a document is (re)indexed, it receives a new message index (based on the timestamp of the update).
Handlers annotated with @HandleDocument will observe these updates as they pass through the document log.
This makes @HandleDocument ideal for live processing, projecting the latest known state, or
cache rebuilds.
Transforming stored documents
Section titled “Transforming stored documents”@HandleDocument can also be used to update documents in place.
If the handler returns a newer revision of the document, Fluxzero will reindex and persist the result:
@HandleDocument("users")UserAccount upgrade(UserAccount oldUser) { return new UserAccount(oldUser.getId(), normalizeEmail(oldUser.getEmail()));}@HandleDocument("users")fun upgrade(oldUser: UserAccount): UserAccount { return UserAccount(oldUser.id, normalizeEmail(oldUser.email))}The returned value replaces the previous document (same ID), only if it has a higher @Revision.
To delete a document from the store, return null:
@HandleDocument("users")UserAccount upgrade(UserAccount user) { return user.isTestUser() ? null : user;}@HandleDocument("users")fun upgrade(user: UserAccount): UserAccount? { return if (user.isTestUser) null else user}Use cases
Section titled “Use cases”- Auto-upcasting legacy documents
- Filling or correcting derived fields
- Cleaning up invalid or deprecated data
- Running background migrations or rehydration jobs
- Real-time analytics and change logging
Handler configuration
Section titled “Handler configuration”You can subscribe to a document collection using any of the following styles:
@HandleDocument— infers the collection from the first parameter of the handler method; this is the preferred style when the document is the first parameter@HandleDocument(documentClass = MyModel.class)— resolves the collection via the model’s@Searchableannotation when the document type cannot be inferred from the first parameter@HandleDocument("myCollection")— binds directly to the named collection
Replay for full collection migration
Section titled “Replay for full collection migration”Want to upgrade all existing documents in a collection? Combine @HandleDocument with replays:
- Create a handler method that returns upgraded documents
- Increment the
@Revisionon the model class - Attach a custom consumer with
@Consumer(minIndex = 0, ...) - Deploy temporarily until migration completes
This is a robust and rapid way to reindex, clean, or refactor your stored documents in-place.
@Consumer(name = "reindex-users", minIndex = 0)class ReindexUsers { @HandleDocument("users") UserAccount upgrade(UserAccount legacyUser) { return fixLegacyState(legacyUser); }}@Consumer(name = "reindex-users", minIndex = 0)class ReindexUsers { @HandleDocument("users") fun upgrade(legacyUser: UserAccount): UserAccount { return fixLegacyState(legacyUser) }}Once the transformation is complete, the handler can be safely removed.
© 2026 Fluxzero