Laravel Database Optimization and Query Performance Guide
The database is the bottleneck in 90% of slow Laravel applications. This guide shows exactly how to find the problems and fix them permanently.
Laravel Database Optimization and Query Performance Guide
In the overwhelming majority of slow Laravel applications, the bottleneck is the database — specifically, poorly structured queries, missing indexes, and Eloquent patterns that look clean in code but generate catastrophic numbers of database round trips at scale. This guide covers the diagnostic process, the most impactful fixes, and the architectural patterns that keep database performance healthy as applications grow.
Finding the Problems
Telescope's database tab shows every query executed during a request, including execution time and query count. Any page load triggering more than 10 queries deserves investigation. Any single query taking more than 100ms needs immediate attention. Use MySQL's EXPLAIN statement to understand how the database executes each slow query. The type column is most important: ALL means a full table scan — almost always a problem on tables with more than a few thousand rows in production.
Database Indexing Strategy
Add indexes to every column used in WHERE clauses, ORDER BY clauses, and JOIN conditions. For queries filtering on multiple columns, composite indexes can be more efficient than individual single-column indexes — the column order matters, with the most selective column first. Covering indexes include all columns needed by a query, eliminating row lookups entirely and providing dramatic performance improvements for frequently executed queries that select a small number of columns.
Eloquent Performance Patterns
Eloquent's all() and get() methods select every column. For collection endpoints, select only the columns your resource actually uses. For large datasets, use chunk() for batch processing and cursor() for single-pass iteration — both process results incrementally without loading full datasets into memory. This is essential for reporting jobs, data exports, and batch operations processing tens of thousands of records.
Query Caching
Cache database query results using Cache::remember() for frequently accessed records and expensive aggregations that change infrequently relative to request volume. Tie cache invalidation to model events so changes automatically invalidate relevant entries without manual cache management code that inevitably becomes stale and incorrect.
Connection Architecture
Laravel with Octane and Swoole maintains persistent database connections, dramatically reducing connection overhead for high-throughput applications. For traditional PHP-FPM deployments, use ProxySQL for MySQL or PgBouncer for PostgreSQL as connection poolers at the infrastructure layer. Configure read replicas — Laravel's built-in read/write connection configuration makes this straightforward to implement and maintain.
Step-by-Step Optimization Process
Step 1: Profile first — identify your 10 slowest queries using Telescope or the MySQL slow query log before making any changes.
Step 2: Add missing indexes — run EXPLAIN on each slow query, add indexes to eliminate full table scans on tables with significant row counts.
Step 3: Fix N+1 queries — add with() eager loading calls to eliminate all N+1 patterns across collection endpoints.
Step 4: Implement query caching with appropriate TTLs and event-based invalidation for expensive, frequently-accessed queries.
Step 5: Monitor continuously — set up database performance monitoring in production with alerting thresholds for query time and connection pool saturation.
Case Study: SaaS Application Optimization
A Laravel SaaS with 50,000 active users was experiencing database timeouts during peak hours. The dashboard endpoint executed 340 queries per request due to deeply nested N+1 loading. After eager loading, 6 index additions, and a query cache for dashboard data: average query time fell from 850ms to 45ms, connection pool saturation disappeared, and the application handled 3x the previous peak load without any infrastructure changes or additional server costs.
Expert Insights
- Index maintenance matters: Indexes degrade on heavily modified tables. Schedule regular OPTIMIZE TABLE operations and monitor index fragmentation on production databases.
- Soft deletes have a cost: Include deleted_at in composite indexes on soft-deleted models to avoid performance degradation on queries that filter by status and deletion state.
- Read replicas before vertical scaling: Adding read replicas is cheaper and more effective for read-heavy applications than scaling the database server vertically to a more expensive instance.
- Test with production-scale data: Performance problems invisible with 1,000 rows in development become catastrophic with 10 million rows in production environments.
Visual Strategy
- Image 1: Database performance metrics dashboard — Unsplash: database monitoring
- Image 2: Server room infrastructure — Pixabay: server room
- Infographic: Database Optimization Decision Tree — from slow query identification through diagnosis to specific fix selection
Conclusion
Database performance is the highest-leverage optimization area in Laravel applications. The systematic process — profiling, indexing, N+1 elimination, caching, and monitoring — produces dramatic results without architectural rewrites. Nectar Digit has reduced query times by 80 to 95% in production Laravel applications using these exact techniques. Contact us if your application is experiencing database performance issues.
Related: Web Development | Laravel Enterprise Architecture
External: Laravel Eloquent Docs | Database — MDN