Most slow apps are slow in the same few places: queries that read too much, cloud code that does too much per request, and an engine sized for last year's traffic. Fix them in that order. More hardware won't save a query that scans a million objects.
Measure first
- Metrics in the dashboard show requests, traffic, the database and the engine's CPU and memory over time. A busy CPU with few requests points at code; a busy CPU with many requests points at capacity.
- Core › Logs, or "show me the errors from the last hour" to your assistant: timeouts and slow-query errors name the class and the query.
- App Checks in the dashboard, or
get_app_advicethrough MCP, flag problems in the database and its configuration.
Queries
Ask for less. Select the fields you show and cap the results:
const query = new Parse.Query('Post');
query.equalTo('author', user);
query.select('title', 'createdAt'); // not the whole object
query.descending('createdAt');
query.limit(20);
const posts = await query.find();
Page with a cursor, not skip. skip(10000) makes the database read and throw away 10,000 objects. Remember the last item you showed and continue after it:
query.lessThan('createdAt', lastPost.get('createdAt'));
Avoid what can't use an index:
matches(regex) that isn't anchored at the start (^), or that ignores case;doesNotExist,notEqualToandnotContainedInon large classes;count()on large classes on every page load: keep a counter instead, updated in anafterSave;containedInwith thousands of values.
Load related objects once. include('author') fetches the authors in the same request. Fetching each in a loop is one request per row.
Index what you filter and sort by. MongoDB needs an index for each common query shape, e.g. author + createdAt for the query above. Without one, every request scans the class. Each index also slows writes a little, so index the queries you actually run, and build indexes on large classes at a quiet time. Not sure which index a slow query needs? Ask your assistant to look at the query and the class, or ask our support.
Cloud code
- Keep triggers short. A
beforeSaveruns on every save, and the client waits for it. Validate and set fields there; move slow work (emails, calls to other services, recalculations) to a background job. - Batch writes.
Parse.Object.saveAll(objects)instead ofsave()in a loop. - Don't fetch what you already have.
request.objectholds the saved object, andrequest.originalits previous version. - Use the master key only where needed (
{ useMasterKey: true }). It skips permission checks, which also hides missing indexes behind "it works for me". - Move heavy work to background jobs. Backfills, reports and cleanups belong in a job you schedule (Core › Jobs), not in a function a client waits for.
- Watch for unbounded loops. A
find()without a limit returns 100 objects; code that "loops until done" over a growing class gets slower every week.
Engine and instances
Your app's server runs on an engine (the CPU and memory of each instance) and a number of instances that share the requests. Both are under Runtime › Engine, and your assistant can change them with an apps:write token.
- A bigger engine helps with CPU-heavy cloud code and large responses.
- More instances help with more concurrent requests, and let one instance restart without your users noticing.
- Auto-scaling (on engines that support it) adds instances under load, between the minimum and maximum you set, and removes them when it's quiet. Set the minimum for your normal traffic and the maximum for your peaks.
Engine and instance changes are billed, and only the app's owner can make them.
High availability
With high availability on, your app always runs at least three instances, with health checks: an instance that stops answering is restarted while the others keep serving. Turn it on for production apps where minutes of downtime cost more than the instances. Turning it on or off resets the scaling limits, so check them afterwards.
Region
Run the app in the region closest to most of your users: every request crosses that distance at least twice. The region is chosen when you create the app; to move an existing app, contact our support.
Parse Server version
Newer Parse Server versions run on newer Node.js, with performance and security fixes. If your app is still on 2.x to 4.x, an upgrade is often the biggest speed-up available. Plan it with plan_parse_server_upgrade (see Build with AI): it lists what your cloud code needs to change first.