> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowwarden.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Properties, storage layout, reactive variants, and hybrid Mongo + Redis setups

`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`.

| Property                      | Type     | Default | Description                                                                                                                                    |
| ----------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `flowwarden.redis.key-prefix` | `String` | `"fw:"` | Prefix prepended to every Redis key written by FlowWarden. Useful for namespacing on a Redis instance shared with other tenants or other apps. |

```yaml application.yml theme={null}
flowwarden:
  redis:
    key-prefix: "tenant-a:"
```

<Note>
  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.
</Note>

## What gets wired

The auto-configuration registers two beans, both guarded by `@ConditionalOnMissingBean`:

| Bean              | Class                  | Replaces                                          |
| ----------------- | ---------------------- | ------------------------------------------------- |
| `lockService`     | `RedisLockService`     | The default `MongoLockService` from the core.     |
| `checkpointStore` | `RedisCheckpointStore` | The 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`:

| Key                               | Type | Fields                                                                                                         | TTL                            |
| --------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| `{prefix}lock:{streamName}`       | Hash | `instanceId`, `acquiredAt`, `expiresAt`                                                                        | `PEXPIREAT` set to `expiresAt` |
| `{prefix}checkpoint:{streamName}` | Hash | `instanceId`, `lastSeenToken`, `lastSeenTimestamp`, `lastProcessedToken`, `lastProcessedTimestamp`, `metadata` | None                           |

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](/reference/checkpoint-store) 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:

```java RedisReactiveConfig.java theme={null}
@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:

```java HybridConfig.java theme={null}
@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](#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

<CardGroup cols={2}>
  <Card title="LockService SPI" icon="lock" href="/reference/lock-service">
    The contract `RedisLockService` implements.
  </Card>

  <Card title="@Checkpoint storage SPI" icon="bookmark" href="/reference/checkpoint-store">
    The contract `RedisCheckpointStore` implements.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/redis/quickstart">
    Add `flowwarden-redis` to your project in 5 minutes.
  </Card>
</CardGroup>
