The Technical Founder's Checklist Before Launching a Web App
Before you launch, there's a lot to get right. Here's a practical checklist covering auth, database, deployment, error handling, and edge cases.
What “Ready to Launch” Actually Means
Most technical founders have felt it: the app works. Local tests pass. The demo looked great. You push to production — and then something breaks in a way you didn’t anticipate, at a moment you couldn’t afford.
Shipping a web app isn’t just about features. There’s a whole layer of infrastructure, security, and operational concerns that only matter once real users start hitting your endpoints. The checklist below covers what technical founders need to verify before going live — auth, database, deployment, error handling, and the edge cases that catch most apps off guard.
This isn’t a list of “nice to haves.” Every item here maps to a real failure mode.
Authentication: The Area Where Most Apps Cut Corners
Auth feels solved — there are libraries, services, tutorials everywhere. And yet it’s the area that causes the most serious production incidents, from account takeovers to data leaks to GDPR violations.
Before launch, go through each of these.
Are you storing passwords correctly?
If you’re rolling your own auth (not recommended, but it happens), passwords must be hashed using bcrypt, Argon2, or scrypt. Never store plain text. Never use MD5 or SHA-1. If your users’ credentials leaked tomorrow, would they be safe?
Do you have email verification?
Unverified email addresses cause cascading problems: wrong people receiving sensitive notifications, inability to recover accounts, abuse via fake registrations. Every user should verify their email before they can use the full app.
For a deeper look at how login systems actually work under the hood, see what user authentication involves and how login systems are built.
Is session management solid?
Check these:
- Sessions expire after inactivity (typically 30 minutes to a few hours, depending on app type)
- Sessions are invalidated on logout — not just cleared from the client
- JWTs, if used, have sensible expiry times and a refresh token strategy
- Old sessions are invalidated when a user changes their password
Are you handling OAuth correctly?
If you support Google, GitHub, or similar login, verify the state parameter is used to prevent CSRF attacks. Confirm that the OAuth callback is validated server-side and not just trusted blindly.
Do you have rate limiting on auth endpoints?
Login, signup, and password reset endpoints should all be rate limited. Without this, they’re trivially brute-forced. Services like Upstash or middleware like express-rate-limit make this easy to add.
For a practical implementation guide, the developer’s guide to adding authentication to a web app covers the setup end to end.
Database: Schema, Backups, and Access Control
The database is where production failures are most expensive. A missing migration, an unindexed column, or an exposed connection string can all end badly.
Is your schema validated and migrated properly?
Your database schema should be managed through migrations — not ad hoc changes made directly against production. Every schema change should be version controlled, reviewable, and repeatable.
Confirm that:
- Migrations are tracked (Prisma migrate, Flyway, Alembic, Knex — pick one and commit to it)
- Running migrations on a fresh database produces the same schema as your production DB
- There’s a rollback plan if a migration fails
Are sensitive columns protected?
Any PII — emails, phone numbers, addresses, payment info — should be considered carefully. Full credit card numbers should never be stored (use Stripe or similar). Emails and names are fine to store but should be protected by row-level security or access controls.
Do you have backups?
This sounds obvious. A lot of teams skip it.
- Automated daily backups, minimum
- Backups stored in a separate location from the primary DB
- You’ve actually tested restoring from backup at least once
If you haven’t set up a managed database yet, the guide to setting up a managed database for your web app walks through the major options.
Are your connection strings secret?
Database credentials should never appear in source code, client-side bundles, or public repositories. Use environment variables. Audit your .env files — verify that .env is in .gitignore and that you haven’t accidentally committed secrets in git history.
Are there indexes on the columns you query?
A query that runs fine against 500 rows will be unusable against 500,000. Before launch, identify every query that filters or sorts by a column and confirm there’s an appropriate index. Check your ORM’s query logs or use EXPLAIN ANALYZE in Postgres to catch slow queries early.
Backend and API: Validation, Authorization, and Error Responses
Your API is a public interface once the app is live. Every endpoint is a potential attack surface.
Are all inputs validated server-side?
Client-side validation is for UX. Server-side validation is for security. Never trust data coming from the client — validate shape, type, length, and format on every incoming request. Libraries like Zod, Joi, or Yup make this straightforward in a Node backend.
For a primer on how APIs work and why this matters, see what a REST API is and how apps communicate.
Is authorization enforced at the data layer?
Authentication confirms who a user is. Authorization determines what they can access. These are separate concerns and both need to be explicit.
Common failure mode: a user can access another user’s data by changing an ID in the URL. This is called an IDOR (Insecure Direct Object Reference) and it’s one of the most common web app vulnerabilities, per the OWASP Top Ten.
Every query that touches user data should include a check that the requesting user owns or has permission to access that data. If you’re building multi-tenant or multi-role functionality, see how to build a multi-user app with roles and permissions.
Do error responses leak internal details?
Stack traces, SQL errors, and internal service messages should never reach the client in production. They expose information that makes attacks easier. Return generic error messages to clients and log the full details server-side.
// Bad
res.status(500).json({ error: "syntax error at or near 'SELECT' — line 42 of query.ts" })
// Good
res.status(500).json({ error: "Something went wrong. Please try again." })
Are you handling async errors?
In Node.js especially, unhandled promise rejections crash processes. Make sure every async route handler has proper try/catch coverage or uses a wrapper that catches rejections automatically. Add a global unhandledRejection handler as a fallback.
Deployment: Going Live the Right Way
A lot of things that work perfectly in development will fail silently or visibly in production if deployment isn’t set up carefully.
Are environment variables configured correctly?
Go through your app’s environment requirements and confirm that every variable your app reads is set in the production environment. Missing env vars cause silent failures, crashes, or degraded functionality that can be hard to trace.
Separate your development, staging, and production configurations explicitly. Never deploy with NODE_ENV=development.
Do you have a CI/CD pipeline?
Shipping by manually running git push and SSHing into a server is fine for very early stages. But before you have real users, set up automated deployment. Continuous deployment means every push to main is automatically tested and deployed — removing human error from the process.
At minimum, run your test suite on every pull request before merging.
Have you verified HTTPS is enforced?
All traffic should be HTTPS. Verify that:
- Your SSL certificate is valid and auto-renewing
- HTTP requests redirect to HTTPS
- You’re using HSTS headers on sensitive routes
Most managed platforms (Vercel, Railway, Fly.io, Render) handle this automatically. If you’re on a raw VPS, confirm it explicitly.
Have you done a cold-start test?
Deploy to a fresh environment. Can you bring the app up from scratch with just your repo and environment variables? This tests your deployment documentation and catches undocumented dependencies. If you can’t reproduce the setup in under an hour, you have a problem.
For a full walkthrough of the deployment process, this guide on how to deploy a web app covers the major platforms and their tradeoffs.
Error Handling and Monitoring: Knowing When Things Break
You can’t fix what you don’t know about. A lot of founders launch and then only find out something is broken when a user emails them.
Do you have error tracking?
Tools like Sentry, Bugsnag, or Datadog capture exceptions in production and give you stack traces, frequency, affected users, and context. This is not optional. You need visibility into what’s breaking.
Set up error tracking before you launch, not after you’ve already missed a week of silent failures.
Do you have logging?
Structured logging (JSON format, not just console.log) lets you search and filter logs when diagnosing issues. Log meaningful events: user signups, payment completions, failed auth attempts, slow queries, third-party API errors.
Keep logs for at least 30 days. Many platforms (Vercel, Fly.io, Railway) provide basic log tailing; for production, consider a log aggregator like Logtail, Better Stack, or Papertrail.
Do you have uptime monitoring?
Know when your app is down before your users tell you. Set up a simple uptime monitor — Better Uptime, UptimeRobot, or Checkly all have free tiers. Point it at your /health endpoint and configure alerts to your email or Slack.
Do you have a /health endpoint?
If you don’t have one, add it. A health check endpoint returns a 200 OK when the app is running and connected to its dependencies (database, cache, external services). It takes 10 minutes to add and makes monitoring and load balancer configuration much simpler.
Edge Cases and Security: The Stuff That Bites Later
These are the items that don’t show up in feature requirements but matter enormously in production.
Have you tested what happens when third-party services are down?
Your app probably depends on several external services: Stripe, SendGrid, S3, OpenAI, Twilio. What happens when any of them returns a 500 or times out?
Every external API call should have:
- A timeout set (don’t let slow APIs block your server indefinitely)
- Error handling that degrades gracefully
- Clear user-facing messaging for failure states
Are you protected against SQL injection and XSS?
If you’re using an ORM like Prisma, Drizzle, or Sequelize, SQL injection is largely handled — but only if you’re using parameterized queries, not string concatenation. Double-check any raw query usage.
For XSS (Cross-Site Scripting): if you render user-provided content to the page, make sure it’s properly escaped. React does this by default for JSX, but dangerouslySetInnerHTML bypasses it. Search your codebase for that pattern and anywhere else user input is rendered directly.
Are file uploads safe?
If users can upload files:
- Validate file type server-side (not just client-side, and not just by extension — check MIME type)
- Set a file size limit
- Store uploads in a dedicated service (S3, Cloudflare R2) — not on the same server as your app
- Never serve uploaded files from the same domain as your app without content-type headers that prevent execution
Have you set appropriate CORS headers?
CORS headers control which origins can make requests to your API. A wildcard (*) is fine during development but dangerous in production if your API handles authenticated data. Lock down your CORS configuration to the specific domains that should have access.
What happens when a user deletes their account?
Account deletion is required for GDPR compliance in Europe. Verify that:
- Users can delete their account
- Deletion removes or anonymizes their PII
- Associated records (posts, orders, sessions) are handled cleanly — either deleted or disassociated
- The deletion is auditable
This is one of those things that’s easy to add before launch and painful to retrofit afterward.
Have you audited your dependencies?
Run npm audit (or your package manager’s equivalent) and address any high or critical severity issues. Third-party packages are a common vector for supply chain attacks. Pin your dependency versions and review any packages that have broad filesystem or network access.
Performance: Baseline Checks Before You Scale
You don’t need to optimize prematurely, but you do need to know your baseline before real traffic arrives.
What are your p95 response times?
Load test your key endpoints — login, the main data fetch, any write-heavy paths. Tools like k6, Artillery, or even Apache Bench can simulate concurrent users. If your p95 response time is above 2-3 seconds under modest load, find the bottleneck before launch.
Are you caching anything?
Not every app needs heavy caching out of the gate, but some obvious candidates are:
- Expensive database reads that return the same data for all users
- Third-party API responses (especially if rate-limited)
- Rendered HTML for public pages
Even a short TTL cache (60 seconds) on a hot endpoint can dramatically reduce database pressure.
Have you set database connection limits?
Connection pooling is critical. Every serverless function invocation can open a new database connection, and databases have hard connection limits. Configure a connection pooler (PgBouncer for Postgres, or use a managed option like Supabase’s built-in pooler) before you see traffic spikes.
How Remy Handles This
This checklist exists because most of this infrastructure has to be assembled by hand. You pick a backend platform, wire up auth, configure your database, set up migrations, choose a deployment target, add monitoring — and that’s before you’ve written a single line of product logic.
The hidden cost of wiring up your own infrastructure is real, and it’s usually underestimated.
Remy takes a different approach. You write a spec — a structured markdown document that describes what your app does, including data types, edge cases, validation rules, and auth requirements. Remy compiles that spec into a full-stack app: backend, typed SQL database, auth with real verification codes and sessions, and deployment. The infrastructure isn’t something you wire up. It’s generated from the spec.
That means many items on this checklist — session management, schema migrations, environment variable handling, HTTPS enforcement — are handled by default, not bolted on afterward.
If you’ve been building manually and want to see what spec-driven development looks like in practice, you can try Remy at mindstudio.ai/remy.
It’s not magic, and it doesn’t eliminate every edge case. But it does eliminate the class of problems where founders ship with missing auth verification or unprotected endpoints because they ran out of time during setup.
Pre-Launch Final Pass: A Condensed Checklist
Before you flip the switch, run through this compressed version:
Auth
- Passwords hashed with bcrypt/Argon2 (if rolling your own)
- Email verification required
- Sessions expire and are invalidated on logout
- Rate limiting on login, signup, and password reset
- OAuth state parameter validated
Database
- Migrations tracked and tested
- Automated backups configured and tested
- Connection strings in environment variables only
- Indexes on commonly queried columns
- PII access controlled by row-level security or equivalent
Backend/API
- Server-side input validation on all endpoints
- Authorization enforced per user — no IDOR vulnerabilities
- Stack traces not returned to clients in production
- Async errors caught and handled
Deployment
- All environment variables set in production
- CI/CD pipeline or automated deployment configured
- HTTPS enforced, HTTP redirects in place
- Cold-start deploy tested from scratch
Monitoring
- Error tracking (Sentry or equivalent) active
- Structured logging in place
- Uptime monitoring configured with alerting
-
/healthendpoint returning meaningful status
Security
- Third-party service failures handled gracefully
- No SQL injection vectors (parameterized queries everywhere)
- XSS vectors reviewed and patched
- CORS headers locked down for production
- Account deletion path exists (GDPR)
-
npm auditrun, critical issues resolved
Frequently Asked Questions
What should technical founders prioritize first when preparing a web app for launch?
Auth and data security come first. Everything else — performance, advanced monitoring, feature completeness — can be improved post-launch. But auth vulnerabilities and exposed data are immediately damaging to users and nearly impossible to recover from reputationally. After that, deployment stability: HTTPS, env vars, and error tracking. The full build and deployment process is worth understanding end to end before you go live.
How do I know if my app’s authentication is production-ready?
Test these specifically: create an account, log in, log out, and verify the session is actually invalidated server-side. Attempt to access an authenticated route without a valid session. Try to register with the same email twice. Attempt 20 rapid login attempts and confirm they’re rate limited. If all of these behave correctly, your auth is reasonably solid.
What’s the most common security mistake technical founders make before launching?
Missing authorization checks at the data layer. It’s extremely common to have authentication (knowing who the user is) without proper authorization (restricting what data they can see). An attacker doesn’t need to break your login system if they can just change a user ID in the URL and access someone else’s records. Every database query that returns user-specific data needs a “does this user own this?” check.
Do I need to worry about GDPR before launch?
If you’re accepting users from Europe — or plan to — yes. At minimum, you need a privacy policy that explains what data you collect and why, the ability for users to request their data be deleted, and no use of data for purposes beyond what users consented to. Account deletion and data export are the two functional requirements most teams miss. Add them before launch, not after.
How should I handle errors that occur in production?
Two tracks: what users see, and what you see. Users should see a clean, helpful error message without technical details. You should see the full error: stack trace, request context, user ID if available, and frequency. Set up an error tracking service like Sentry immediately — it captures this automatically with minimal setup. Don’t rely on log files you have to SSH in to read.
Is it okay to launch without a staging environment?
For a very early MVP with a small, known user base, it can be acceptable. But even a cheap staging environment that mirrors production will save you from deploying broken code to real users. The bare minimum is to test every migration against a copy of production data before running it on production. Once you’re past early alpha, a staging environment is not optional.
Key Takeaways
- Auth vulnerabilities and data leaks are the most urgent pre-launch risks — treat them as blocking issues, not backlog items.
- Database migrations, backups, and connection pooling are infrastructure concerns, not feature work — they need to be in place before real users arrive.
- Error tracking and uptime monitoring take an hour to set up and give you visibility you can’t operate without.
- Authorization (what users can access) is a separate concern from authentication (who they are) — both need explicit implementation.
- GDPR requirements, especially account deletion, are easier to build before launch than to retrofit under pressure later.
If you want to skip the manual infrastructure assembly and work from a spec that generates all of this by default, try Remy at mindstudio.ai/remy.