RU Send your project
All articles

The first thousand users: what breaks first

Not the server and not the load, but queries in loops, missing indexes, heavy work inside requests and email limits. How to find them early.

· 4 min readCodeInfrastructure

A thousand users isn’t many. The server that handled the demo will usually handle them too. What breaks isn’t the hardware but the assumptions that held while the database had twenty rows and one test account. The good news is that these failures are fairly predictable.

Queries in a loop

The most common cause of slow pages in AI-written code is the N+1 problem. A page loads a list of orders with one query, then fetches the customer for each order with another query, the items with another, the shipping status with another. With ten orders that’s thirty fast queries, and nobody notices. With five hundred it’s fifteen hundred, and the page takes several seconds.

How to find it: turn on query logging in development and open any page with a list. If the number of queries grows with the number of rows on screen, that’s it. The fix is to load related data in a single query, with a join, an in (...), or your ORM’s eager loading.

Missing indexes

While a table is small, the database reads all of it in milliseconds and a missing index goes unnoticed. Then the table grows and the same query starts taking hundreds of milliseconds, for everyone at once.

First candidates for an index:

  • foreign keys, since Postgres doesn’t index them automatically;
  • columns you filter on most: record owner, status, date;
  • columns you sort paginated lists by.

explain analyze helps with a specific query: if the plan shows a sequential scan of a large table to find a few rows, an index is missing. Just don’t index everything in sight; each index slows down writes.

Lists without pagination

An endpoint that returns “all of a user’s projects” or “all messages in a chat” works while there are five. An active user eventually has thousands, and the response weighs megabytes. Adding pagination now is easier than explaining later why the app is slowest for your most loyal customers.

Heavy work inside the request

Sending an email, generating a PDF, calling an AI model, processing an image: all of these often run right inside the HTTP handler. The person waits, the connection stays open, and if the external service is slow, the request times out. Worst of all is when the action half-completes: the order is created but the email never goes out.

This kind of work belongs in a background job queue. The request saves the data and enqueues a job; the job runs separately, with retries on failure. The person gets a response immediately, not whenever a third-party service gets around to answering.

Email limits

Confirmation emails, password resets and notifications suddenly become part of the critical path. And email has limits you discover the moment they run out: a daily cap on a mailbox or free plan, a sending rate limit, a block after spam complaints.

What to check:

  • your sender’s daily limit, and how many emails you send today;
  • whether SPF, DKIM and DMARC are set up; without them, a noticeable share of your mail lands in spam;
  • whether newsletters and login emails share a channel. If a marketing send uses up the limit, people stop receiving their login codes.

Database connections

Serverless functions on platforms like Vercel or Netlify open a database connection per instance. As traffic grows, so does the number of instances, and the database hits its limit on concurrent connections. From the outside it looks like random errors that come and go. The fix is a connection pooler between the functions and the database. Managed databases usually have one already; you just need to switch it on and use the right connection string.

How to find this early

The cheapest way is to generate ten times your current data on staging and walk through the main flows. Slow pages show up immediately. The second habit is a slow query log in production: anything slower than, say, half a second gets recorded, and someone looks at it once a week.

SUBXCAT can go through your project before your users find these spots, and fix the most expensive ones.

Want us to do this for you?

Tell our assistant about your project — a rough estimate in five minutes, a review in 48 hours.

Book an intro call 20 minutes: an engineer, a designer and a marketer look at your project with you.
Book a call