Problem
Loading everything up front slows startup and page loads and wastes memory and bandwidth on content most users never touch. Eager fetching of related records also multiplies database work.
Also known as: deferred-loading, on-demand-loading
Defer loading data, code or resources until they are actually needed.
Loading everything up front slows startup and page loads and wastes memory and bandwidth on content most users never touch. Eager fetching of related records also multiplies database work.
Lazy loading postpones work until it is demanded. It trades a small delay at first use for a large saving up front, and it applies to code, images, data and object relationships.
Frontend example with route-level code splitting:
const Reports = lazy(() => import("./Reports"));
// downloaded only when the user opens the Reports route
Images use the loading="lazy" attribute or an intersection observer to fetch as they approach the viewport. Backend ORMs return a proxy for an association and query only when it is read:
orders = db.orders(limit=50)
for o in orders: print(o.customer.name) # 50 extra queries
The loop above is the N plus 1 trap. Fix it with eager or batched loading for the known access pattern: one query for orders, one query for the customers by id list.
Mitigate perceived delay with prefetching. Start loading a chunk when the user hovers a link or when the browser is idle, and reserve space with skeletons or fixed image dimensions to avoid layout shift.
Lower; less data transferred
Low
Medium: loading states and hidden I/O
N plus 1 queries triggered inside a loop
Lazy chunk fails to load on a poor network, leaving a broken view
Layout shift when deferred content pops in