Memory leaks in Spring Boot applications are silent killers.
Your application:
- Starts fine
- Works fine in dev
- Passes tests
- Slowly crashes in production after hours or days
One of the most common hidden causes is improper bean scope usage.
This guide explains:
- What bean scopes are
- How wrong scope choices cause memory leaks
- Real production scenarios
- How to fix and prevent them permanently
What Is a Memory Leak in Spring Boot?
A memory leak happens when:
- Objects are no longer needed
- But still referenced
- And cannot be garbage collected
Over time:
- Heap usage keeps growing
- GC becomes aggressive
- Application slows down
- Eventually crashes with
OutOfMemoryError
Spring Boot does not automatically protect you from this.
Understanding Bean Scopes in Spring Boot
Every Spring bean has a scope — how long it lives in memory.
Common Spring Boot Bean Scopes
| Scope | Lifetime |
|---|---|
singleton | Entire application lifetime |
prototype | New instance per request |
request | One HTTP request |
session | One user session |
application | ServletContext lifetime |
Default scope = singleton
Why Improper Bean Scopes Cause Memory Leaks
Spring manages beans — not your object usage logic.
If a bean:
- Lives longer than it should
- Holds references to short-lived objects
- Accumulates state
Then memory leaks are inevitable.
🚨 Most Dangerous Scenario: Stateful Singleton Beans
The Root Problem
Singleton beans live for the entire application lifetime.
If they store:
- User data
- Request data
- Large collections
- Caches without limits
Memory will never be released.
❌ Bad Example (Very Common in Production)
@Service
public class UserSessionTracker {
private List<UserSession> sessions = new ArrayList<>();
public void track(UserSession session) {
sessions.add(session);
}
}
What goes wrong:
- Bean is singleton
- List keeps growing
- Old sessions never removed
- Heap keeps increasing
This is a classic memory leak.
✅ Correct Approach
- Avoid storing state in singleton beans
- Use request/session scope if needed
- Or external stores (Redis, DB)
Prototype Beans Injected into Singleton Beans (Hidden Leak)
Why This Is Dangerous
@Component
@Scope("prototype")
public class HeavyObject {}
Injected into:
@Service
public class Processor {
@Autowired
private HeavyObject heavyObject;
}
Problem:
Processoris singleton- Prototype is created once
- Never released
- Defeats prototype purpose
This creates unexpected memory retention.
✅ Correct Solution
Use:
ObjectProviderApplicationContext- Factory pattern
@Autowired
private ObjectProvider<HeavyObject> provider;
public void process() {
HeavyObject obj = provider.getObject();
}
Request / Session Scope Used Incorrectly
Common Production Mistake
Using @RequestScope or @SessionScope beans inside singleton services without proxying.
@Service
public class OrderService {
@Autowired
private UserContext userContext;
}
If UserContext is session-scoped:
- References can leak across sessions
- Memory grows with user count
✅ Correct Usage
@SessionScope
@Component
public class UserContext {}
And use proxy mode implicitly (Spring Boot handles this correctly when annotated properly).
Caching Inside Beans Without Eviction
Another Silent Memory Leak
@Component
public class CacheService {
private Map<String, Object> cache = new HashMap<>();
}
Issues:
- No eviction
- No size limit
- Runs forever
✅ Fix Using Proper Cache Strategy
Use:
- Caffeine
- Redis
- Spring Cache abstraction
Never build unlimited in-memory caches in singleton beans.
Static Fields Inside Spring Beans
Extremely Dangerous Pattern
@Component
public class MetricsHolder {
public static List<String> logs = new ArrayList<>();
}
Why this leaks:
- Static lives beyond Spring context
- Not managed by container
- Survives reloads
- Hard to clean
Avoid static state in Spring applications.
Bean Lifecycle & Memory Leaks
Improper cleanup causes leaks.
Missing Cleanup Hooks
Beans that:
- Open connections
- Create threads
- Use executors
Must clean up on shutdown.
✅ Correct Cleanup
@PreDestroy
public void cleanup() {
executor.shutdown();
}
Or implement DisposableBean.
How to Detect Memory Leaks in Production
Symptoms
- Gradual heap growth
- Increasing GC time
- Slow response times
- Sudden crashes
Tools to Use
- JVM heap dump
- VisualVM
- JConsole
- Production monitoring (APM)
Best Practices to Prevent Bean Scope Memory Leaks
1. Keep Singleton Beans Stateless
No user data, no request data.
2. Use Proper Scope for State
- Request data →
request - User data →
session - Shared logic →
singleton
3. Avoid Manual Object Caching
Let cache frameworks manage memory.
4. Be Careful with Prototype Beans
Never inject prototypes directly into singletons.
5. Clean Resources Properly
Threads, connections, streams must be closed.
Production Checklist (Quick Scan)
✔ Singleton beans have no mutable state
✔ No unbounded collections
✔ No static state
✔ Proper bean scopes used
✔ Cleanup hooks implemented
If any ❌ → memory leak risk.
Internal Links
Insert these exact anchor texts naturally:
- Core concept: How Spring Boot Creates Beans – Bean Lifecycle Simplified
- Related issue: BeanCreationException in Spring Boot
- Performance: ApplicationContext Startup Slow in Production
- Configuration: Spring Boot Configuration Loading Order
- Profiles: Profile-Based Bean Loading in Spring Boot
FAQs
Can singleton beans cause memory leaks?
Yes, if they hold state or references to short-lived objects.
Does Spring automatically clean unused beans?
No. Spring manages lifecycle, not object usage logic.
Are prototype beans safer than singleton?
Only if used correctly. Misuse can still cause leaks.
Can bean scopes affect performance?
Yes. Wrong scope increases memory usage and GC pressure.
Is memory leak possible without OutOfMemoryError?
Yes. Performance degradation happens long before crashes.
Final Summary
Memory leaks in Spring Boot are rarely obvious.
Most production leaks happen because:
- Developers misuse bean scopes
- Stateful logic is placed in singleton beans
- Cleanup is ignored
Understanding bean scopes is mandatory for production-grade Spring Boot systems.
If you fix this correctly, you prevent:
- Random crashes
- Slow degradation
- Emergency production incidents
