NoSQL & Caching Dependencies
A catalog of the Spring Boot starters for MongoDB, Redis, and Elasticsearch, plus the caching starters that sit in front of any slow data source.
Introduction
Not every application fits neatly into rows and columns. Some data is naturally document-shaped (a user profile with nested addresses), some is best kept as fast, disposable key-value pairs (a session or a rate-limit counter), and some needs to be searched by relevance rather than exact match (a product catalog search bar). This lesson covers the Spring Boot starters that plug into each of those shapes, plus the caching layer that speeds up repeated reads regardless of where the data lives.
- How to store and query documents with spring-boot-starter-data-mongodb.
- How to use Redis for key-value storage and session state with spring-boot-starter-data-redis.
- How to wire up full-text search with spring-boot-starter-data-elasticsearch.
- How to add a caching layer with spring-boot-starter-cache and Caffeine.
MongoDB: Document Storage
MongoDB stores data as JSON-like documents instead of table rows. It is a good fit when your objects are naturally nested (an order with embedded line items) or when the schema changes often between records. spring-boot-starter-data-mongodb gives you a MongoTemplate, repository support via MongoRepository, and auto-configuration for the Mongo driver — you only need to supply a connection URI.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>spring.data.mongodb.uri=mongodb://localhost:27017/shopdb@Document(collection = "products")public class Product {
@Id private String id; private String name; private double price; private List<String> tags;
// constructors, getters, setters}
public interface ProductRepository extends MongoRepository<Product, String> { List<Product> findByTagsContaining(String tag);}
@Servicepublic class ProductService {
private final ProductRepository repository;
public ProductService(ProductRepository repository) { this.repository = repository; }
public Product save(Product product) { return repository.save(product); }
public List<Product> findByTag(String tag) { return repository.findByTagsContaining(tag); }}Click Run to see what this code prints.
Redis: Key-Value & Sessions
Redis is an in-memory key-value store, commonly used for caching, session storage, rate limiting, and pub/sub messaging. spring-boot-starter-data-redis brings in Lettuce (the default Redis client) and auto-configures a RedisTemplate you can inject anywhere you need fast, ephemeral storage.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency>spring.data.redis.host=localhostspring.data.redis.port=6379@Servicepublic class SessionTokenService {
private final RedisTemplate<String, String> redisTemplate;
public SessionTokenService(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; }
public void storeToken(String sessionId, String token) { redisTemplate.opsForValue() .set("session:" + sessionId, token, Duration.ofMinutes(30)); }
public String getToken(String sessionId) { return redisTemplate.opsForValue().get("session:" + sessionId); }}For a full HTTP session backed by Redis instead of just raw key-value operations, add spring-session-data-redis alongside this starter — it replaces the in-memory HttpSession with one persisted in Redis, so sessions survive app restarts and work across multiple instances behind a load balancer.
Elasticsearch: Full-Text Search
A SQL LIKE query does not scale for search — it cannot rank results by relevance, handle typos, or search across multiple fields efficiently. Elasticsearch is a search engine built for exactly that. spring-boot-starter-data-elasticsearch gives you an ElasticsearchRepository interface backed by the Elasticsearch REST client.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>@Document(indexName = "articles")public class Article {
@Id private String id;
@Field(type = FieldType.Text) private String title;
@Field(type = FieldType.Text) private String body;}
public interface ArticleRepository extends ElasticsearchRepository<Article, String> { List<Article> findByTitleContaining(String keyword);}Click Run to see what this code prints.
Caching with Caffeine
Caching stores the result of an expensive call (a slow query, a remote API call) so the next request for the same input can skip straight to the answer. spring-boot-starter-cache turns on Spring's caching abstraction (the @Cacheable/@CacheEvict annotations), and com.github.ben-manes.caffeine:caffeine supplies a fast, in-memory cache implementation to back it.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId></dependency><dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId></dependency>@Configuration@EnableCachingpublic class CacheConfig {
@Bean public CacheManager cacheManager() { CaffeineCacheManager manager = new CaffeineCacheManager("products"); manager.setCaffeine(Caffeine.newBuilder() .maximumSize(500) .expireAfterWrite(Duration.ofMinutes(10))); return manager; }}
@Servicepublic class ProductService {
@Cacheable("products") public Product findById(String id) { System.out.println("Hitting the database for " + id); return repository.findById(id).orElseThrow(); }
@CacheEvict(value = "products", key = "#id") public void updateProduct(String id, Product product) { repository.save(product); }}Click Run to see what this code prints.
Comparison Table
| Dependency | Data Shape | Best For |
|---|---|---|
| spring-boot-starter-data-mongodb | JSON-like documents | Flexible, nested schemas |
| spring-boot-starter-data-redis | Key-value pairs | Sessions, caching, counters |
| spring-boot-starter-data-elasticsearch | Indexed text documents | Full-text and fuzzy search |
| spring-boot-starter-cache + caffeine | In-memory cache entries | Speeding up repeated method calls |
Common Mistakes
- Using Redis as a system of record instead of a cache — data in Redis can be evicted or lost, so it should never be the only copy of important data.
- Forgetting @EnableCaching, which silently makes @Cacheable a no-op.
- Reaching for Elasticsearch when a database index and a LIKE query would be plenty fast enough for the actual data volume.
Frequently Asked Questions
It is the easiest path — docker run mongo, docker run redis, and docker run elasticsearch each get you a local instance in seconds without installing anything natively.
Yes, and it is a very common combination — MongoDB as the source of truth, Redis as a fast cache in front of it.
No. Spring's cache abstraction also works with Redis, EhCache, and others — Caffeine is simply the most common choice for a local, in-process cache.
Summary
MongoDB, Redis, and Elasticsearch each solve a different data-shape problem, and Spring Boot's caching starter lets you speed up any of them (or a plain SQL database) with a single annotation. Next, we secure the endpoints sitting in front of all this data.