Redis Store
Redis store for high-throughput, low-latency deployments.
The Redis store uses Grove KV with the redisdriver for key-value storage. It stores entities as JSON blobs and uses Redis sorted sets and sets for indexing and querying.
Usage
Standalone
import (
"github.com/xraph/grove/kv"
_ "github.com/xraph/grove/kv/drivers/redisdriver"
redisstore "github.com/xraph/relay/store/redis"
)
store, err := kv.Open("redis", "redis://localhost:6379/0")
if err != nil {
log.Fatal(err)
}
s := redisstore.New(store)
r, err := relay.New(relay.WithStore(s))With Forge extension
When using the Forge extension with Grove KV, the store is resolved from the DI container:
app.Use(extension.New(
extension.WithGroveKV(""), // uses the default grove kv.Store
))Or via YAML config:
extensions:
relay:
grove_kv: ""Data model
Entities are stored as JSON blobs under prefixed keys. Indexes use Redis sorted sets (scored by timestamp) and sets for efficient lookup.
Key prefixes
| Prefix | Purpose |
|---|---|
relay:evtype:<id> | Event type entity |
relay:ep:<id> | Endpoint entity |
relay:evt:<id> | Event entity |
relay:del:<id> | Delivery entity |
relay:dlq:<id> | DLQ entry entity |
Index keys
| Key pattern | Type | Purpose |
|---|---|---|
relay:z:evtype:all | Sorted set | All event types by creation time |
relay:z:ep:tenant:<tid> | Sorted set | Endpoints per tenant |
relay:z:evt:all | Sorted set | All events by creation time |
relay:z:evt:tenant:<tid> | Sorted set | Events per tenant |
relay:z:del:pending | Sorted set | Pending deliveries by next_attempt_at |
relay:z:del:ep:<eid> | Sorted set | Deliveries per endpoint |
relay:z:dlq:all | Sorted set | All DLQ entries by failure time |
relay:s:evtype:active | Set | Active (non-deprecated) event type IDs |
relay:s:ep:tenant:<tid>:enabled | Set | Enabled endpoint IDs per tenant |
Unique constraints
| Key pattern | Purpose |
|---|---|
relay:u:evtype:name:<name> | Event type name uniqueness |
relay:u:evt:idem:<key> | Idempotency key uniqueness |
Migrations
Migrate() is a no-op -- Redis does not require schema migrations. Keys and indexes are created on demand as entities are stored.
Internals
| Aspect | Detail |
|---|---|
| Driver | Grove KV with redisdriver (go-redis v9) |
| Migrations | No-op |
| Dequeue | Sorted set range + atomic key update |
| Transactions | Redis single-key atomicity |
| JSON fields | All entities stored as JSON blobs |
| Pagination | Client-side offset/limit on sorted set results |
| Ping | kv.Ping(ctx) |
| Close | Closes the KV store |
When to use
- High-throughput, low-latency delivery pipelines.
- When Redis is already part of your infrastructure.
- Ephemeral or cache-friendly workloads where Redis persistence (RDB/AOF) is acceptable.
- Workloads that benefit from Redis clustering for horizontal scaling.
Limitations
- No multi-key transactions -- operations are atomic per key only.
- Pagination is applied client-side after fetching sorted set members.
- Data durability depends on Redis persistence configuration (RDB, AOF, or none).