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

Hey everyone,

I’m working on a client portal project hosted on 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

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.

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.