Avoid loading transactions and aggregating them in memory. Push grouping and projection to SQL, bound the time range, and cache only when the freshness requirement allows it. Example: var totals = await db.Orders.AsNoTracking() .Where(x => x.RestaurantId == tenant.RestaurantId && x.OutletId == tenant.OutletId && x.CreatedAt >= from) .GroupBy(x => x.Status) .Select(g => new { Status = g.Key, Count = g.Count(), Sales = g.Sum(x => x.Total) }) .ToListAsync(ct); Index tenant and date filters, inspect the generated SQL and execution plan, and consider a summary table for expensive historical dashboards. Return all widgets from one consistent snapshot where consistency matters.
Backbencher Developer · · 0 likes