Skip to main content
flowwarden-redis is auto-configured via RedisStreamCoreAutoConfiguration. It activates when both spring-data-redis is on the classpath and a StringRedisTemplate bean is available — which is the default whenever you include spring-boot-starter-data-redis.

Properties

All properties are bound to RedisStreamCoreProperties under the prefix flowwarden.redis.
PropertyTypeDefaultDescription
flowwarden.redis.key-prefixString"fw:"Prefix prepended to every Redis key written by FlowWarden. Useful for namespacing on a Redis instance shared with other tenants or other apps.
application.yml
flowwarden:
  redis:
    key-prefix: "tenant-a:"
The Redis connection itself (host, port, password, SSL, cluster mode) is configured through the standard Spring Boot spring.data.redis.* properties. flowwarden-redis consumes whichever StringRedisTemplate Spring Boot exposes — pointing it at a single instance, a Sentinel set, or a cluster is transparent.

What gets wired

The auto-configuration registers two beans, both guarded by @ConditionalOnMissingBean:
BeanClassReplaces
lockServiceRedisLockServiceThe default MongoLockService from the core.
checkpointStoreRedisCheckpointStoreThe default MongoCheckpointStore from the core.
Conditions applied to the auto-configuration class:
  • @AutoConfiguration(after = RedisAutoConfiguration.class) — runs after Spring Boot’s Redis auto-config so the StringRedisTemplate bean is already available.
  • @ConditionalOnClass(RedisTemplate.class) — skip entirely if spring-data-redis is not on the classpath.
  • @ConditionalOnBean(StringRedisTemplate.class) — skip if no StringRedisTemplate exists in the context (for example, when the Redis starter is present but no connection is configured).
The @ConditionalOnMissingBean on each @Bean defers to any user-declared LockService or CheckpointStore, so user beans win without further configuration.

Storage layout

flowwarden-redis stores all of its state in Redis Hashes, keyed by stream name and namespaced with key-prefix:
KeyTypeFieldsTTL
{prefix}lock:{streamName}HashinstanceId, acquiredAt, expiresAtPEXPIREAT set to expiresAt
{prefix}checkpoint:{streamName}HashinstanceId, lastSeenToken, lastSeenTimestamp, lastProcessedToken, lastProcessedTimestamp, metadataNone
Resume tokens (lastSeenToken, lastProcessedToken) are encoded as base64 BSON so they round-trip exactly the same bytes Mongo’s Change Stream cursor returned, and metadata is stored as a JSON string.

Atomic operations

  • Lock acquire / renew / release run as Lua scripts so the compare-and-set guarantee (only the current holder can renew or release the lock) holds across concurrent Redis clients without round-trips.
  • saveSeen / saveProcessed use targeted HSET against the relevant pair of fields. This preserves the dual-token semantics from the core (lastSeenToken advances on every event received; lastProcessedToken advances only after handler success) without the read-modify-write that the SPI’s default implementations would do — see the @Checkpoint storage SPI section for the dual-token rationale.

Reactive variants

The reactive implementations (ReactiveRedisLockService, ReactiveRedisCheckpointStore) ship in the library but are not auto-configured. Spring Boot’s Redis auto-configuration creates both a blocking StringRedisTemplate and a ReactiveStringRedisTemplate whenever Lettuce is on the classpath — there is no reliable conditional that would let the auto-config pick one without surprising users in a typical Spring WebFlux setup. Wire them explicitly when you want non-blocking Redis ops:
RedisReactiveConfig.java
@Configuration
public class RedisReactiveConfig {

    @Bean
    LockService lockService(ReactiveStringRedisTemplate template,
                            RedisStreamCoreProperties properties) {
        return new ReactiveRedisLockService(template, properties.getKeyPrefix());
    }

    @Bean
    CheckpointStore checkpointStore(ReactiveStringRedisTemplate template,
                                    RedisStreamCoreProperties properties) {
        return new ReactiveRedisCheckpointStore(template, properties.getKeyPrefix());
    }
}
The @Bean declarations above win over the auto-configured blocking ones thanks to @ConditionalOnMissingBean.

Hybrid Mongo + Redis

Because each backend bean is independently auto-configured (and independently guarded by @ConditionalOnMissingBean), you can keep one in Mongo and the other in Redis by overriding only the one you want to move. For example — locks in Redis, checkpoints in Mongo:
HybridConfig.java
@Configuration
public class HybridConfig {

    // Force the Mongo checkpoint store, overriding the Redis auto-configured one.
    @Bean
    CheckpointStore checkpointStore(MongoTemplate mongo) {
        return new MongoCheckpointStore(mongo);
    }

    // RedisLockService is left to the auto-config — nothing else to declare.
}
The reverse split (checkpoints in Redis, locks in Mongo) works symmetrically.

Disabling

There is no dedicated enabled flag. To disable a Redis-backed bean, declare a different bean of the same type — or remove flowwarden-redis from the dependencies. Two practical patterns:
  • Switch one bean back to Mongo — declare a @Bean MongoLockService / @Bean MongoCheckpointStore (see Hybrid Mongo + Redis).
  • Disable both — drop flowwarden-redis from the build. The core’s MongoDB backends auto-configure as soon as flowwarden-redis is no longer on the classpath.

See Also

LockService SPI

The contract RedisLockService implements.

@Checkpoint storage SPI

The contract RedisCheckpointStore implements.

Quickstart

Add flowwarden-redis to your project in 5 minutes.