A small mistake in a Spring Boot API can quietly kill performance. I’ve seen endpoints that should respond in ~100ms end up taking 4+ seconds, even though CPU, memory, and database indexes all look fine. In many cases the issue turns out to be something simple like a findAll() call in a JPA repository that loads far more data than needed and triggers an N+1 query problem. Just replacing it with a targeted query or DTO projection can reduce the response time dramatically. Sometimes performance problems are not about infrastructure or scaling. They’re about how we write our queries. Curious to hear from other backend engineers — what’s the smallest code change that gave you the biggest performance improvement? #Java #SpringBoot #BackendDevelopment
Small Spring Boot Mistakes That Kill Performance
More Relevant Posts
-
In this 2nd article : scaling bulk search in Spring Boot with parallel batch jobs and controlled concurrency A few lessons stood out for me: [1] parallelism helps, but only until it starts hurting upstream systems [2] chunking is not just a batch setting, it becomes a stability boundary [3] partial failure handling matters as much as throughput [4] caching repeated enrichment work can remove a surprising amount of unnecessary load One of the biggest shifts for me was moving away from a more limited blocking flow into parallel batch jobs while still keeping pressure on downstream systems under control. I wrote the full breakdown here: https://lnkd.in/ggb2ZCF2 #SpringBoot #Java #Backend #SystemDesign #SoftwareEngineering #SpringBatch #DistributedSystems
To view or add a comment, sign in
-
Ever wondered how Spring Boot sets up a DataSource, EntityManagerFactory, and transactions — without you writing a single line of config? That's auto-configuration. And I just wrote my first blog post breaking down exactly how it works. What's covered: → The role of META-INF/spring/AutoConfiguration.imports → @ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty → How condition evaluation happens before any bean is created If you've ever typed @SpringBootApplication and moved on without questioning it — this one's for you. This is my first blog, so if I've missed anything or something could be explained better — feel free to drop a comment. Happy to discuss and improve! 🔗 Link in the comments! #SpringBoot #Java #Backend
To view or add a comment, sign in
-
-
While working on backend systems, we’ve traditionally used ExecutorService to handle concurrent transactions — especially for processing shipping data and storing it in the database. It works well… but managing threads at scale always needs careful tuning. Recently, I started evaluating virtual threads (Java 21) as an alternative. On paper, they look great: ✔️ Lightweight threads ✔️ Better scalability for concurrent tasks ✔️ Simpler code compared to complex thread pools But while exploring this, a few practical concerns came up: ❌ Not all operations benefit → CPU-heavy tasks don’t gain much ❌ Blocking calls still matter → If you block on I/O without proper handling, gains reduce ❌ Debugging & monitoring → Traditional tools may not give clear visibility ❌ Library compatibility → Some older libraries may not be optimized for virtual threads 🧠 What I realized: Virtual threads are powerful… but they need to be used in the right kind of workload. 💡 My takeaway: They are great for I/O-heavy, high-concurrency systems — but not a direct replacement for everything. Still exploring this space, especially how it fits into real production systems. Would love to hear if anyone has tried virtual threads in real-world use cases. #Java #Java21 #VirtualThreads #Backend #Concurrency #SystemDesign #SoftwareEngineering
To view or add a comment, sign in
-
Virtual threads Traditional thread-per-request models were expensive. Virtual threads make concurrency cheap, scalable, and easier to reason about. Every new Spring Boot service has spring.threads.virtual.enabled=true set by default. The era of reactive-by-default for I/O-bound work is fading fast — teams are writing straightforward, blocking-style code and still achieving WebFlux-level concurrency. Before Virtual Threads: → You needed reactive programming (WebFlux, RxJava) to handle high concurrency → Reactive code is hard to read, hard to debug, hard to onboard → Context switching between threads was expensive at scale After Virtual Threads: → Write simple, imperative code → JVM handles millions of lightweight threads natively → Same or better throughput — zero reactive complexity Why this matters: → Reactive code was powerful but painful to write and debug → Virtual threads give you the same performance with half the complexity #Java #SpringBoot #BackendDevelopment #Microservices #VirtualThreads
To view or add a comment, sign in
-
-
Why is your Spring Boot application slow? It’s rarely because of the framework. Most performance issues come from how resources are used. Here are practical techniques that actually make a difference when optimizing a Spring Boot application: 1. Reduce blocking operations Slow database calls or external APIs hold threads and limit throughput. Optimize queries and avoid unnecessary waits. 2. Use connection pooling effectively Database connections are expensive. Instead of creating a new connection for every request, applications use a connection pool. Connections are reused, which improves performance and scalability. 3. Tune thread pools Default settings are not always optimal. Adjust server thread counts based on CPU and request patterns. 4. Add caching where appropriate Repeated database calls can be avoided using caching (e.g., in-memory or Redis). 5. Optimize database queries Use indexing, avoid N+1 queries, and monitor slow queries. 6. Use asynchronous processing Offload non-critical work using async methods or background jobs. 7. Monitor before optimizing Use tools (Actuator, logs, profiling) to identify real bottlenecks before making changes. Key takeaway: Performance is not about making everything faster. It’s about removing bottlenecks and using resources efficiently. #Java #SpringBoot #BackendDevelopment #Performance #SoftwareEngineering
To view or add a comment, sign in
-
Spring Boot features that took me years to discover (wish someone had told me sooner): 1. @ConfigurationProperties over @Value Stop injecting individual properties Bind entire configuration blocks to typed classes You get validation for free with @Validated 2. Actuator /health with custom indicators Don't just expose the default health check Add checks for your downstream dependencies Your ops team will thank you at 2am 3. @Async with proper thread pool config Spring's default Async executor is a thread-per-task executor Configure ThreadPoolTaskExecutor with proper bounds Unbounded queues + async = memory leak waiting to happen 4. @Transactional pitfalls Self-invocation bypasses the proxy readOnly=true is an optimization hint, not a guarantee Understand your propagation levels 5. Spring Boot DevTools for productivity Automatic restart, LiveReload, property defaults Should be in every developer's setup 6. Profiles done right application-{profile}.yml not just one giant file Never put secrets in application.yml Use Spring Cloud Config or environment variables for production What Spring Boot feature do you wish you'd known earlier? #Java #SpringBoot #Backend #SoftwareEngineering #Microservices
To view or add a comment, sign in
-
Great list. Adding a few things that took me just as long to figure out. One that does not get talked about enough is Hibernate's truncateMappedObjects() for integration test cleanup. Most engineers wrap their tests in @Transactional and call it done. The problem is that a transaction that never commits is not testing what actually runs in production. FlushMode never triggers, LazyInitializationExceptions that would blow up in prod pass silently, and database constraints never get validated. Using SchemaManager to truncate before each test and letting the service layer own its transactions gives you real production-equivalent behavior in your test suite. Another one is DataSource-Proxy over spring.jpa.show-sql. The built-in property only prints SQL to console with no bind parameter values and no batching visibility. DataSource-Proxy gives you all of that and lets you automatically detect N+1 query issues during testing before they ever reach production. Most engineers also do not realize that Resilience4j integrates directly into Spring Boot via application.yml with zero custom code. Circuit breaker, retry with exponential backoff, rate limiter and bulkhead all configurable as beans. By the time you write a custom retry mechanism from scratch, this was already available in your dependency tree. Flyway is another one that looks optional until the day a schema change goes to production without a migration script and takes down your application. Schema changes versioned and applied automatically on startup, the same way across every environment. Once you use it you cannot imagine managing databases without it. The last one is @TransactionalEventListener. Most engineers use @EventListener for application events but it fires regardless of transaction outcome. @TransactionalEventListener fires only after the transaction successfully commits. For things like sending emails, pushing to a message queue, or triggering downstream calls after a database write, this is the correct tool. Using @EventListener for those cases means your side effects fire even when the transaction rolls back.
Java Full Stack Developer | Spring Boot | React.js | Microservices | Azure | Docker | Kubernetes | Kafka
Spring Boot features that took me years to discover (wish someone had told me sooner): 1. @ConfigurationProperties over @Value Stop injecting individual properties Bind entire configuration blocks to typed classes You get validation for free with @Validated 2. Actuator /health with custom indicators Don't just expose the default health check Add checks for your downstream dependencies Your ops team will thank you at 2am 3. @Async with proper thread pool config Spring's default Async executor is a thread-per-task executor Configure ThreadPoolTaskExecutor with proper bounds Unbounded queues + async = memory leak waiting to happen 4. @Transactional pitfalls Self-invocation bypasses the proxy readOnly=true is an optimization hint, not a guarantee Understand your propagation levels 5. Spring Boot DevTools for productivity Automatic restart, LiveReload, property defaults Should be in every developer's setup 6. Profiles done right application-{profile}.yml not just one giant file Never put secrets in application.yml Use Spring Cloud Config or environment variables for production What Spring Boot feature do you wish you'd known earlier? #Java #SpringBoot #Backend #SoftwareEngineering #Microservices
To view or add a comment, sign in
-
Most developers think Spring handles 500 requests “all at once.” It doesn’t. Here’s what actually happens: Spring Boot (via embedded Tomcat in Spring Boot) uses a thread pool to handle incoming requests. Each request follows this path: → Request arrives at Tomcat → A free thread is assigned → DispatcherServlet routes it to your @RestController → Controller → Service → Database → Response is returned → Thread goes back to the pool That’s it. No magic. ━━━━━━━━━━━━━━━━━━━━ What happens when all threads are busy? → New requests are placed in a queue → If the queue is full, requests may be rejected (e.g., 503 errors depending on configuration) ━━━━━━━━━━━━━━━━━━━━ The real bottleneck isn’t traffic, it’s blocked threads. Consider this: A slow database call takes 3 seconds × 200 threads = Your system can stall under moderate load This is why backend engineers focus on: Thread pool tuning Reducing blocking operations Asynchronous processing (@Async) Efficient database access (connection pooling) Non-blocking architectures (Spring WebFlux) Key takeaway: Performance is not about handling more requests. It’s about how efficiently your threads are utilized. #Java #SpringBoot #Concurrency #BackendDevelopment #SoftwareEngineering #JavaDeveloper
To view or add a comment, sign in
-
I fixed a 4-second Spring Boot API without scaling anything. ⚠️the real problem? 47 database queries per request. 🧩we thought it was a performance issue. so we tried: • more RAM • indexes • monitoring CPU nothing changed. 🔍then I checked the SQL logs. and saw the real issue: → N+1 query problem → JPA lazy loading → 47 queries for a single API call 🛠️ the fix was simple: replace multiple queries with one optimized query: JOIN FETCH everything in a single DB call. 📉 result: • 4000ms → 190ms • 47 queries → 1 • DB CPU dropped massively 📌 lesson: don’t scale first. first understand what your code is doing to the database. #SpringBoot #Java #Backend #SystemDesign #APIs #SoftwareEngineering
To view or add a comment, sign in
-
Unlock the full potential of your Spring applications this spring! Virtual threads are here to revolutionize concurrency, allowing millions of I/O-bound requests without blocking. Discover how to harness this power with Spring Boot 3.2, just a single property away. Read the full article to learn more: https://lnkd.in/gQKvdECS #concurrency #Java #Java21 #Performance #SpringBoot
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development