Skip to content

Protecting sensitive data

Fluxzero offers built-in support for handling sensitive information with care using the @ProtectData and @DropProtectedData annotations.

These tools help prevent sensitive fields (e.g., passwords, SSNs, tokens) from being unnecessarily stored, logged, or retained — supporting compliance with data protection standards like GDPR and ISO 27001.


To prevent a field from being stored with the rest of a message payload, annotate it with @ProtectData:

public record RegisterCitizen(String name,
@ProtectData String socialSecurityNumber) {
}

When this message is dispatched, the socialSecurityNumber will be:

  • Offloaded to a separate data vault when the message is published externally
  • Redacted from the main payload (not visible in logs or message inspectors)
  • Re-injected automatically when the message is handled

This happens transparently — you can access the field as usual in handler methods.

If a message is handled only by a local handler with logMessage = false, the original value remains in memory and is passed directly to that handler without a KV write or read. External fallback and logMessage = true keep the normal vault-backed behavior. @LocalOnly messages never externalize protected values.


If the protected data should only be retained temporarily, annotate the handler method with @DropProtectedData:

@HandleCommand
@DropProtectedData
void handle(RegisterCitizen command) {
validate(command.getSocialSecurityNumber());
...
}

Once this handler completes:

  • The injected socialSecurityNumber is permanently deleted from storage, or discarded from memory for a local-only dispatch.
  • Future replays will deserialize the message with that field omitted.

  • Temporary use of sensitive tokens or credentials
  • Compliance with data minimization and retention policies
  • Preventing accidental exposure in logs or audits

During replays, if a message with protected fields is re-invoked after data has been dropped, those fields will be missing or set to null.


Handlers can choose how to respond when protected values referenced by a message are no longer available:

@HandleEvent(onMissingProtectedData = MissingProtectedDataPolicy.SKIP)
void handle(CitizenRegistered event) {
...
}

The available policies are:

  • HANDLE: invoke silently with unavailable fields set to null (SDK default)
  • WARN: log a warning and invoke with unavailable fields set to null
  • SKIP: skip only this handler invocation and advance tracking normally
  • FAIL: fail through the consumer’s normal error handling
  • DEFAULT: inherit from the consumer or application configuration

The effective policy is resolved from the handler, consumer, builder, application property, and finally the SDK default. Configure the application fallback with DefaultFluxzero.builder().onMissingProtectedData(...) or:

fluxzero.dataProtection.onMissingProtectedData=WARN

For environment variables, both FLUXZERO_DATA_PROTECTION_ON_MISSING_PROTECTED_DATA and the compact Spring-style FLUXZERO_DATAPROTECTION_ONMISSINGPROTECTEDDATA are supported.

When tracking metrics are enabled, SKIP emits an IgnoreMessageEvent with reason missingProtectedData.


  • Only fields can be annotated with @ProtectData (not method parameters).
  • Dropping data is irreversible. Make sure all processing is complete before it is removed.
  • Support for nested structures is currently limited — annotate each sensitive field explicitly.

© 2026 Fluxzero