Why a small page can execute many queries
An N+1 problem occurs when an initial query loads a collection and later code executes another query for each item. A page containing orders and customer names may look simple while its database work grows with every displayed order. The important clue is repeated query shape and growth with collection size, not merely one slow SQL statement.
Eloquent supports eager loading, which retrieves intended relationships before the application traverses them. However, loading every reachable relationship can replace excessive query count with excessive memory and rows. Begin with the response the business actually needs and keep pagination, tenant scope and authorization intact.
Setup: establish a reproducible page fixture
Choose one endpoint and synthetic records with multiple parents, children and missing optional relationships. Record the application release, page size and selected filters. Capture query counts and total query time for that request using approved local or staging instrumentation. Redact bindings that contain personal or commercial information.
Repeat the request with a larger page size while keeping the same data distribution. Inspect the controller, resource serializer and template, because relationship access can happen after the initial repository query. Also inspect access from a child back to its parent: the Laravel relationship documentation notes that N+1 behavior can still occur in such traversal even when an earlier relationship was eager loaded.
Illustrative incident: the serializer creates the load
In an illustrative account portal, an engineer optimizes the order query but the endpoint remains slow. A serializer subsequently reads each order's account manager. The repeated manager query is absent from the controller and therefore missed during the first review. This is a teaching scenario, not a named or anonymized client engagement.
Build a trace that connects response fields to relationship reads. Count the SQL generated by the whole response, including conditional fields and accessors. A benchmark that stops immediately after the initial query does not test the user's actual request.
Troubleshooting: compare growth and scope
| Finding | Evidence | Decision |
|---|---|---|
| Similar SQL repeats per record | Normalized query shapes and call sites | Eager load the relationship used by the response |
| Queries are few but rows are enormous | Row counts and hydrated object graph | Constrain relationships and response fields |
| Only one filter is slow | Filter plan and selected relationships | Investigate its SQL independently of N+1 |
| A child traversal triggers new queries | Serializer and inverse relation access | Review that precise access direction |
Query count alone is not the performance objective. Two queries returning an unnecessarily large dataset may be worse than several small bounded queries. Collect memory, rows and request duration alongside the count.
Corrective action with a bounded response
Declare the relationships required by this endpoint, constrain their fields and preserve the identifiers needed to join them correctly. Use aggregates when the interface needs a count rather than complete child records. Do not add broad global eager loading simply because it fixes one screen; unrelated jobs and endpoints may inherit the extra work.
Where the framework version supports development detection of unintended lazy loading, use it as a regression signal. Evaluate violations in the real response path. Keep the intended behavior for optional or absent relationships explicit, and never remove a tenant predicate to make the query easier to optimize.
Verification, performance objective and SOP
Compare small and large fixture pages. Confirm that query growth follows the intended bounded plan, response records remain correct, and no extra fields become exposed. Include empty relationships and a second tenant as negative tests. Measure representative latency without inventing a performance percentage from a single workstation run.
An internal SLO should concern useful page responses within an agreed latency envelope. Query budgets are diagnostic guardrails supporting that objective, not a contractual SLA by themselves. The SOP should retain the fixture, expected relationship plan, instrumentation method and rollback revision. Escalate separately when the remaining delay is a database plan, network or capacity issue.
Explore Laravel development and database administration for application and query review.
Technical reference
Laravel Eloquent relationships, reviewed 19 October 2026. Follow documentation matching the installed product version.