Skip to content

Firefly Framework - Cache

CILicenseJavaSpring Boot

Reactive, provider-agnostic cache abstraction for Spring Boot — a unified CacheAdapter API with Caffeine built in and pluggable Redis, Hazelcast, JCache and PostgreSQL adapters discovered via SPI.


Table of Contents

Overview

Firefly Framework Cache is the core cache abstraction of the framework. It defines a single, reactive (Mono-based) CacheAdapter port and a FireflyCacheManager facade, so application code caches against one stable interface and never couples itself to a specific cache technology. Switching from a local in-process cache to a distributed one is a matter of adding an adapter dependency and changing one property — no code change.

Out of the box the module ships a single provider: Caffeine, a high-performance in-memory (L1) cache that is always available with zero extra dependencies. The other providers — Redis, Hazelcast, JCache (JSR-107) and PostgreSQL — live in their own adapter modules. They register with the core through the CacheProviderFactory SPI (Java ServiceLoader), so dropping an adapter JAR on the classpath makes its CacheType available to the CacheManagerFactory automatically. The core has no compile-time dependency on any distributed provider; optional infrastructure beans (Redis connection factory, Hazelcast instance, JCache manager, R2DBC connection factory) are resolved reflectively only when present.

CacheManagerFactory creates independent, namespaced cache managers on demand — each with its own key prefix, TTL and provider — so different framework modules (web idempotency, webhook dedup, etc.) can share infrastructure without colliding. When a distributed provider is selected, the factory can transparently wrap it with SmartCacheAdapter, a write-through L1 (Caffeine) + L2 (distributed) composite that serves reads from local memory and backfills L1 on L2 hits. A CacheType.AUTO mode lets the framework pick the best available provider by SPI priority (Redis → Hazelcast → JCache → Caffeine).

The module integrates with fireflyframework-observability to expose cache metrics (Micrometer) and a Spring Boot Actuator HealthIndicator, and depends on fireflyframework-kernel for the shared exception hierarchy.

Features

  • Unified reactive cache portCacheAdapter with get, put (incl. TTL), putIfAbsent, evict, evictByPrefix, clear, exists, keys, size, getStats and getHealth, all returning Mono.
  • Caffeine built in — high-performance in-memory L1 adapter (CaffeineCacheAdapter) configured via CaffeineCacheConfig; always available with no extra dependencies.
  • Pluggable providers via SPI — Redis, Hazelcast, JCache (JSR-107) and PostgreSQL ship as separate adapter modules discovered through the CacheProviderFactoryServiceLoader SPI; the core never compiles against them.
  • FireflyCacheManager facade — delegates to the active provider with optional fallback and resilient error handling (cache failures degrade gracefully to misses instead of propagating).
  • CacheManagerFactory — creates multiple independent cache managers, each with its own name, key prefix, TTL and CacheType.
  • Smart L1+L2 cacheSmartCacheAdapter provides write-through composite caching (local Caffeine over a distributed provider) with optional L1 backfill on reads.
  • Automatic provider selectionCacheType.AUTO and AutoCacheSelectionStrategy pick the best available provider by SPI priority.
  • Pluggable serializationCacheSerializer SPI with a default JSON implementation (JsonCacheSerializer) backed by a dedicated cacheObjectMapper (JSR-310 aware).
  • Observability — Micrometer CacheMetrics and an Actuator CacheHealthIndicator, auto-wired via CacheObservabilityAutoConfiguration.
  • Zero-config auto-configurationCacheAutoConfiguration registers a primary FireflyCacheManager, the factory and serializer; fully configurable through validated CacheProperties (firefly.cache.*).

Requirements

  • Java 21+ (Java 25 recommended)
  • Spring Boot 3.x
  • Maven 3.9+
  • A distributed cache backend (Redis, Hazelcast, JCache provider or PostgreSQL) only if you add the corresponding adapter module — Caffeine requires nothing extra.

Installation

<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-cache</artifactId>
<!-- Version managed by the Firefly BOM / parent POM -->
</dependency>

The version is managed by the fireflyframework-parent / Firefly BOM; omit <version> when your project inherits or imports it.

Quick Start

With the dependency on the classpath, CacheAutoConfiguration provides a primary FireflyCacheManager (Caffeine by default). Inject it and use the reactive API:

importorg.fireflyframework.cache.manager.FireflyCacheManager;
importorg.springframework.stereotype.Service;
importreactor.core.publisher.Mono;
importjava.time.Duration;
importjava.util.Optional;
@ServicepublicclassProductService {
privatefinalFireflyCacheManagercache;
privatefinalProductRepositoryrepository;
publicProductService(FireflyCacheManagercache, ProductRepositoryrepository) {
this.cache = cache;
this.repository = repository;
}
publicMono<Product> findById(Stringid) {
returncache.<String, Product>get(id, Product.class)
.flatMap(cached -> cached
.map(Mono::just)
.orElseGet(() -> repository.findById(id)
.flatMap(product -> cache
.put(id, product, Duration.ofMinutes(10))
.thenReturn(product))));
}
publicMono<Boolean> evict(Stringid) {
returncache.evict(id);
}
}

Need a dedicated, namespaced cache (separate key prefix, TTL and provider)? Inject the factory:

importorg.fireflyframework.cache.core.CacheType;
importorg.fireflyframework.cache.factory.CacheManagerFactory;
importorg.fireflyframework.cache.manager.FireflyCacheManager;
FireflyCacheManageridempotencyCache = factory.createCacheManager(
"http-idempotency",
CacheType.AUTO, // Redis if present, else Caffeine"firefly:http:idempotency",
Duration.ofHours(24));

Cache Provider Adapters

The core ships Caffeine. To enable a distributed provider, add its adapter module and select it via firefly.cache.default-cache-type (or AUTO). Each adapter self-registers through the CacheProviderFactory SPI.

ProviderAdapter moduleCacheTypeNotes
Caffeine(built into core)CAFFEINEIn-memory L1, always available
Redisfireflyframework-cache-redisREDISReactive, Lettuce-based distributed cache
Hazelcastfireflyframework-cache-hazelcastHAZELCASTDistributed in-memory data grid
JCache (JSR-107)fireflyframework-cache-jcacheJCACHEStandards-based (Ehcache, Infinispan, …)
PostgreSQLfireflyframework-cache-postgresPOSTGRESR2DBC-backed persistent distributed cache
<!-- Example: add Redis as the distributed (L2) provider -->
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-cache-redis</artifactId>
</dependency>
firefly:
cache:
default-cache-type: REDIS # or AUTO to auto-select the best available provider

When a distributed provider is active and firefly.cache.smart.enabled is true, the factory wraps it with SmartCacheAdapter to provide an L1 (Caffeine) + L2 (distributed) write-through cache.

Configuration

All properties are bound from the firefly.cache.* prefix into the validated CacheProperties class. Defaults shown below.

firefly:
cache:
enabled: true # master switch for the cache librarydefault-cache-type: CAFFEINE # CAFFEINE | REDIS | HAZELCAST | JCACHE | POSTGRES | NOOP | AUTOmetrics-enabled: true # publish Micrometer cache metricshealth-enabled: true # expose the Actuator cache health indicatorstats-enabled: true # collect cache statisticscaffeine: # built-in in-memory (L1) providerenabled: truecache-name: defaultkey-prefix: "firefly:cache"maximum-size: 1000expire-after-write: 1hexpire-after-access: # disabled by defaultrefresh-after-write: # disabled by defaultrecord-stats: trueweak-keys: falseweak-values: falsesoft-values: falseredis: # used by fireflyframework-cache-redisenabled: truecache-name: defaulthost: localhostport: 6379database: 0username:
password:
connection-timeout: 10scommand-timeout: 5skey-prefix: "firefly:cache"default-ttl: # no TTL unless setenable-keyspace-notifications: falsemax-pool-size: 8min-pool-size: 0ssl: falsepostgres: # used by fireflyframework-cache-postgresenabled: falsecache-name: defaulthost: localhostport: 5432database:
username:
password:
schema: publiccache-table: firefly_cache_entrieskey-prefix: ""default-ttl: 30mauto-create-schema: truemax-pool-size: 10min-pool-size: 1smart: # L1 (Caffeine) + L2 (distributed) compositeenabled: truewrite-strategy: WRITE_THROUGH # only WRITE_THROUGH is implementedbackfill-l1-on-read: true

Key properties:

  • default-cache-type — selects the provider. CAFFEINE (default) keeps everything in-process. Set to a distributed type once its adapter is on the classpath, or use AUTO to let the framework pick the highest-priority available provider.
  • enabled — when false, CacheAutoConfiguration backs off entirely.
  • caffeine.* — sizing and eviction for the built-in L1 cache (maximum-size, expire-after-write, expire-after-access, refresh-after-write, reference strength).
  • redis.* / postgres.* — connection, pooling, key-prefix and TTL settings consumed by the respective adapter modules (hazelcast and jcache adapters add their own properties).
  • smart.* — controls the write-through L1+L2 composite applied automatically over distributed providers.
  • Observability — metrics and health honor firefly.observability.metrics.enabled and firefly.observability.health.enabled (both default true).

Documentation

In-repo guides live under docs/:

Framework-wide documentation and the module catalog are available in the Firefly Framework organization.

Contributing

Contributions are welcome. Please read the CONTRIBUTING.md guide for details on our code of conduct, development process, and how to submit pull requests.

License

Copyright 2024-2026 Firefly Software Foundation.

Licensed under the Apache License, Version 2.0. See LICENSE for details.

About

Reactive multi-provider cache abstraction for Spring Boot: Caffeine plus pluggable Redis, Hazelcast & PostgreSQL

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors