Skip to main content
Stackbastion

Draft, not yet published

Load-testing your app before a Product Hunt launch

7 July 2026· 5 min read · by Stackbastion

You’re launching on Product Hunt next week. If it goes well, a few hundred people hit your app in the same hour, maybe the same minute. Right now you have no idea whether it holds up, because the most concurrent users you’ve ever had is you and two friends. Finding out live, in front of your launch audience, is the worst possible time. Here’s how to find your breaking point this week instead.

Why launch traffic breaks apps that seemed fine

The gap between “works for me” and “works for 300 people at once” is huge, and nothing in normal use reveals it. You test by clicking around one at a time. Real launch traffic is dozens or hundreds of requests landing together, and that’s a completely different load on the same code.

Two things break under concurrency that never break solo. First, your database connection pool. Each visitor’s request wants a connection, and once they run out, every new request fails at once, not gradually. Second, any slow operation. A query that takes 800ms is invisible when you’re the only user and catastrophic when 200 of them stack up and hold resources at the same time.

A load test simulates that crowd on purpose, before the real one arrives, so you learn your ceiling in private.

How to load-test in an afternoon

You’ll pick a tool, run a baseline, ramp up until something breaks, and fix the first thing that breaks. Two good free tools: hey for a quick single-endpoint blast, and k6 for realistic multi-step scenarios. Start with hey because it’s a one-liner.

Step 1: a quick baseline with hey.

Install it (brew install hey on Mac, or grab the binary), then throw a realistic burst at your most important URL. This sends 500 total requests with 50 running concurrently:

hey -n 500 -c 50 https://your-app.com/

Read the output. The two numbers that matter:

  • Latency distribution. Look at the 95th percentile, not the average. If p95 is 3 seconds, one in twenty visitors waits three seconds. Averages hide the users having a bad time.
  • Status code distribution. Every response should be 200. If you see 500 or 503 or timeouts, you already found a breaking point at just 50 concurrent.

Step 2: ramp until it breaks.

Push the concurrency up in steps and watch where it falls apart:

hey -n 1000 -c 100 https://your-app.com/
hey -n 2000 -c 200 https://your-app.com/

Somewhere the error rate climbs or latency spikes. That number is your current ceiling. Now you know what a “good” launch can actually survive.

Step 3: test a real user journey with k6.

A homepage hit isn’t your real load. Users log in, load data, submit forms. k6 scripts a realistic flow and ramps virtual users over time. Save this as load-test.js:

import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  stages: [
    { duration: "30s", target: 50 },   // ramp to 50 users
    { duration: "1m", target: 200 },   // ramp to 200 and hold
    { duration: "30s", target: 0 },    // ramp back down
  ],
  thresholds: {
    http_req_duration: ["p(95)<1000"], // 95% of requests under 1s
    http_req_failed: ["rate<0.01"],    // less than 1% errors
  },
};

export default function () {
  // Load the homepage
  const home = http.get("https://your-app.com/");
  check(home, { "home 200": (r) => r.status === 200 });

  // Hit a real data endpoint the app depends on
  const api = http.get("https://your-app.com/api/items");
  check(api, { "api 200": (r) => r.status === 200 });

  sleep(1); // pretend the user reads the page
}

Run it:

k6 run load-test.js

k6 fails the run if it crosses your thresholds, so you get a clear pass or fail instead of squinting at numbers. If http_req_failed climbs during the 200-user hold, your app can’t take a strong launch as-is.

Step 4: fix the first thing that breaks, then re-run.

Under load, the first failure is almost always the database. If errors mention connections (too many clients, remaining connection slots), you need a connection pooler like PgBouncer in front of Postgres so hundreds of requests share a small pool. If it’s latency, find the slow query with explain analyze and add the missing index. Fix one thing, run the test again, and watch the ceiling move up. Repeat until the app holds your realistic worst case with headroom.

Aim to survive at least double your expected peak. If you think a great launch is 150 concurrent, make sure the app is clean at 300. Launch day is not the day to discover the limit.

Or, we do it for you

A production audit includes a load test against your real endpoints, tells you the concurrency your app survives today, and hands you the ranked fixes to raise it before launch day. If you want a second pair of eyes on your setup regardless of what you built it with, get a free production audit.

FAQ

How much traffic does a Product Hunt launch actually bring?

A strong feature can send a few thousand visitors across the day, with sharp spikes of a few hundred concurrent in the busiest minutes, especially right after it goes live and when it hits the daily email. The daily total matters less than the peak concurrency, because it’s the simultaneous crowd that breaks things. Plan for the spike, not the average.

Will load-testing my own app get me in trouble?

Testing your own infrastructure is fine, but if you’re on a shared or managed host, check their terms first, because a hard load test can look like an attack. Run it against your production or a production-like staging environment, and avoid pointing heavy load at third-party APIs you don’t own. Test what you’re responsible for.

hey or k6, which should I use?

Both, in that order. hey is a single command for a fast gut-check on one endpoint, perfect for a first look. k6 scripts a realistic multi-step user journey with ramping load and pass/fail thresholds, which is what you want before actually launching. Start with hey, graduate to k6.

What’s a good result?

Under your realistic peak load, every response is a success and your 95th-percentile latency stays under about a second, with no climbing error rate as the test holds. If you can double your expected peak and still pass, you’re in good shape. If errors appear at your expected peak, fix the first failure and test again before launch.