Most Spring Boot applications don't need full-blown sharding frameworks. They just need a safe, predictable way to separate reads and writes.
Routemate is a lightweight database routing library designed for this exact need. It focuses on the 80% most common read/write separation use cases, without introducing new infrastructure, SQL rewriting, or operational complexity.
If you've ever thought:
- "ShardingSphere is too heavy for this"
- "I just want read replicas, not a distributed database"
- "I want something that behaves like Spring, not replaces it"
Then Routemate is for you.
- Zero-Code Read/Write Splitting
- Multi-Read Replica Support
- Round-Robin (Default)
- Random
- Weighted Round-Robin
- Background Health Checks
- Automatic Master Fallback
- Programmatic DataSource Management
- Per-DataSource HikariCP Tuning
With Routemate, you don't change your code. You just annotate your transactions correctly.
- Java 17+
- Spring Boot 3.x
- Docker & Docker Compose (for running the examples)
Add the dependency to your build.gradle (assuming published or local project):
dependencies {
implementation 'io.github.krongdev:routemate-spring-boot-starter:1.0.1'
}Configure your data sources in application.yml:
spring:
datasource:
# Master DataSource (Standard Spring Boot config)
url: jdbc:mysql://localhost:3306/mydb
username: user
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
routemate:
enabled: true
# Configure Read Replicas
reads:
slave-1:
url: jdbc:mysql://localhost:3307/mydb
username: read_user1
password: read_password1
driver-class-name: com.mysql.cj.jdbc.Driver
weight: 1
slave-2:
url: jdbc:mysql://localhost:3308/mydb
username: read_user2
password: read_password2
driver-class-name: com.mysql.cj.jdbc.Driver
weight: 2
# Routing Strategy
routing:
load-balance-strategy: weighted-round-robinRoutemate allows fine-grained HikariCP configuration per read replica. This is useful when replicas have different performance characteristics or connection limits.
routemate:
reads:
slave-1:
# -- datasource connection pool (HikariCP) --
pool:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000If
poolis not specified, Routemate falls back to Spring Boot's default HikariCP settings.
Simply use Spring's standard @Transactional annotation. Routemate handles the rest.
@Service
public class UserService {
private final UserRepository userRepository;
// Routes to Master (Write)
@Transactional
public User createUser(String name) {
return userRepository.save(new User(name));
}
// Routes to Read Replica (Slave)
@Transactional(readOnly = true)
public Optional<User> getUser(Long id) {
return userRepository.findById(id);
}
}