When building scalable systems with Spring Boot, running multiple instances of your application is a common practice and using @GenratedValue in Entity classes is even more common. At first glance it looks very safe but distributed environments have their own nuances. Let’s discuss, what can go wrong ?
What Is @GeneratedValue?
@GeneratedValue is a JPA annotation used to specify how the primary key of an entity should be generated. You typically use it like this:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// other fields…
}
JPA provides four main strategies for ID generation:
- AUTO
- IDENTITY
- SEQUENCE
- TABLE Each of these behaves differently — and not all of them are safe in a multi-instance deployment.
The Core Problem: ID Collisions
In a multi-instance environment (e.g., cloud deployment with horizontal scaling), each instance may try to generate IDs independently. Without a shared mechanism, this can cause:
- Duplicate primary keys
- Failed inserts due to constraint violations
- Data corruption or overwriting
- Performance bottlenecks
Strategy Breakdown: When Collisions Happen
Here’s how each generation strategy behaves:
1. GenerationType.IDENTITY Safe
- Uses the database’s auto-increment feature.
- Each insert operation generates the ID in the DB.
- No risk of collision, even across instances. Drawback: Slower inserts due to round-trip to the DB.
2. GenerationType.SEQUENCE Safe with Correct Configuration
- Uses a database sequence to generate IDs.
Hibernate can preallocate ID blocks to reduce DB hits using allocationSize.
Risk of collision if:Each instance uses its own local sequence (e.g., in-memory DB).
allocationSize is not properly configured or mismatched with the database.
Best Practice:
@SequenceGenerator(
name = "user_seq_gen",
sequenceName = "user_sequence",
allocationSize = 50
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq_gen")
private Long id;
Ensure:
- All instances use the same shared database.
- The DB sequence increments match the allocationSize.
3. GenerationType.TABLE High Collision Risk
Stores the current ID in a table.
Reads, increments, and writes the ID.
Risk of collision:
- Without proper locking or isolation, two instances may read the same ID before it’s updated. Recommendation: Avoid high-concurrency, multi-instance setups.
4. GenerationType.AUTO Unpredictable
- JPA chooses the strategy based on the database and provider.
- Could resolve to SEQUENCE, IDENTITY, or TABLE. Risk of collision: Depends on what strategy gets selected. Recommendation: Avoid using AUTO in distributed systems unless you know exactly what strategy it maps to.
Alternatives for Distributed Systems
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
private UUID id;
Use UUIDs
Globally unique
- Safe across all instances
- No DB coordination needed Drawback: Larger index size; less efficient than numeric IDs
Use Custom Distributed ID Generators (e.g., Snowflake)
Use libraries or microservices that generate distributed, sortable, and unique IDs:
- Snowflake
- ULID / KSUID
- Redis/Zookeeper-based counters These are ideal for high-scale systems needing numeric IDs without DB hits.
Summary
Conclusion
When building Spring Boot applications that run in multi-instance environments, ID generation is a critical design choice. Misconfigured ID strategies can lead to hard-to-debug issues in production.
Stick to safe strategies like UUID, properly-configured sequences, or distributed ID services to ensure your app scales safely.
Stay Connected
Connect with us on LinkedIn and follow us on Facebook & Instagram to stay in the loop with the latest insights on skills, hiring, and workforce transformation.
📩 Subscribe to our Newsletter and YouTube channel for fresh perspectives on GenAI-driven talent evaluation. Thinkhumble.in

Top comments (0)