# Optimizing Velo backend code & data collection queries for faster page load times

**URL:** <https://forum.wixstudio.com/t/optimizing-velo-backend-code-data-collection-queries-for-faster-page-load-times/80188>\
**Category:** Ask the community\
**Tags:** wix-data, code, cms, design, wix\
**Created:** [October 12, 2026, 4:40pm UTC](https://forum.wixstudio.com/t/optimizing-velo-backend-code-data-collection-queries-for-faster-page-load-times/80188 "2026-10-12T16:40:40Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![igotu](https://avatars.discourse-cdn.com/v4/letter/i/db5fbb/32.png) [@igotu](https://forum.wixstudio.com/u/igotu)\
**Post date:** [October 12, 2026, 4:40pm UTC](https://forum.wixstudio.com/t/optimizing-velo-backend-code-data-collection-queries-for-faster-page-load-times/80188/1 "2026-10-12T16:40:40Z")

</div>

Hey everyone,

I’m working on a client portal project hosted on [igotucorp.com](http://igotucorp.com) and running into a bit of a performance snag with some Velo backend queries.

We have a dynamic page that pulls user activity logs and custom metrics from a Data Collection containing several thousand rows. During peak traffic hours, the frontend data loading causes a noticeable delay before the repeater populates.

Here is a simplified snippet of what we’re running in our backend module (`dashboard.jsw`):

JavaScript

```javascript
import { backendQuery } from 'wix-data-backend';

export async function fetchUserMetrics(userId) {
    try {
        let results = await wixData.query("UserActivityLogs")
            .eq("owner", userId)
            .descending("_createdDate")
            .limit(50)
            .find();
            
        return results.items;
    } catch (error) {
        console.error("Error fetching metrics:", error);
        return null;
    }
}

```

**What we’ve optimized so far:**

- Added indexed fields on the `owner` and `_createdDate` columns in the collection.

- Limited the query results to 50 items to keep payloads light.

**My Questions:**

1. Are there recommended caching strategies in Velo (using `wix-window` memory or similar) to reduce redundant backend calls for static user metadata?

2. Is it better practice to handle heavy aggregation using custom backend web modules or stick to client-side data hooks?

Would love to hear how others are handling high-frequency data fetching efficiently in Velo.

Thanks,

**Working in**  
e.g. Wix Studio Editor, Wix Editor, Dev Mode, CMS, etc.

**Site link**  
If this is happening on a site, include a live or test site link

**What I’m trying to do**  
Describe the goal or outcome you’re hoping for

**What I’ve tried so far**  
Let us know what you’ve already tested, changed, or searched

**Extra context**  
Anything else that might help - edge cases, screenshots, etc.

---

<div class="post-metadata">

**Author:** ![Ecom\_swift\_LLC](https://sea1.discourse-cdn.com/wix/user_avatar/forum.wixstudio.com/ecom_swift_llc/32/122562_2.png) [@Ecom\_swift\_LLC](https://forum.wixstudio.com/u/Ecom_swift_LLC)\
**Post date:** [October 12, 2026, 7:22pm UTC](https://forum.wixstudio.com/t/optimizing-velo-backend-code-data-collection-queries-for-faster-page-load-times/80188/2 "2026-10-12T19:22:43Z")

</div>

Good setup already with the indexes and the limit(50). A few things that helped us on similar client-portal dashboards:

Caching: for data that does not change every request (user metadata, config, anything mostly static per session), wix-storage session storage on the client is usually enough and skips a backend round trip entirely. If you want server-side caching across users, there is a caching helper in wix-data-backend (and the newer backend caching utilities) you can wrap fetchUserMetrics in with a short TTL, 30-60s is plenty for a dashboard that is not real-time. That alone usually kills most of the “redundant backend calls” problem without adding real staleness.

Aggregation: put it in a backend web module, not client-side hooks. Dataset/page hooks run per visitor on every load, so any aggregation there repeats the work each time and ships more JS to the client. A .jsw function keeps the heavy lifting server-side, lets you control exactly what gets returned, and is the only place you can safely do multi-collection joins or math across the full dataset before sending 50 rows down.

One more thing worth checking since you are already a few thousand rows in: skip()-based pagination degrades the deeper you go. If anything downstream of this paginates past page 1, switch to cursor-based paging (the result object’s .next() from find()) instead of bumping skip() - it stays fast regardless of how deep the user scrolls. And if “custom metrics” means anything computed (counts, sums, rollups), consider precomputing those into a small separate collection on a scheduled job rather than aggregating at request time - much cheaper than recalculating on every page load during peak hours.

If this helped, please mark it as Solved.

---

<div class="post-metadata">

**Author:** ![Ecom\_swift\_LLC](https://sea1.discourse-cdn.com/wix/user_avatar/forum.wixstudio.com/ecom_swift_llc/32/122562_2.png) [@Ecom\_swift\_LLC](https://forum.wixstudio.com/u/Ecom_swift_LLC)\
**Post date:** [October 15, 2026, 7:13am UTC](https://forum.wixstudio.com/t/optimizing-velo-backend-code-data-collection-queries-for-faster-page-load-times/80188/3 "2026-10-15T07:13:49Z")

</div>

Two things in the snippet first. `wix-data-backend` isn’t a module, the import should be `import wixData from 'wix-data';`. And with the indexes you already added, the query itself is fine for a few thousand rows, so the delay is more likely in how the page calls it.

Return only what the repeater needs: add `.fields("title", "value", "_createdDate")` (your own field names) so the payload stays small.

For caching, skip `wix-window`. On the page, `memory` from `wix-storage-frontend` works for per-visit data you don’t want to refetch, and `session` survives a refresh. In the backend, don’t rely on module-level variables, they can reset between calls.

Heavy aggregation belongs in the backend. Use `wixData.aggregate()` with `.group()` and `.sum()` inside your .jsw rather than pulling rows to the client and summing there. If the metrics are mostly static, precompute them: a scheduled job (jobs.config) can write a daily summary row per user to a small collection, so the page reads one item instead of aggregating on every load.

Keep data hooks light, since a `beforeQuery` or `afterQuery` hook runs on every read. On the page, start the fetch in `onReady` without blocking the layout and show a loader until it resolves.

Check the Site Monitoring logs during peak hours to see whether the time is going to the query or to the round trip.

If this helped, please mark it as Solved.
