All posts

August 10, 2026

Collecting waitlist emails without building a database

Launching something new usually starts the same way: a single landing page, a headline, and a signup box asking for an email. The box takes five minutes to build. The part nobody accounts for is everything behind it — where do the emails go, how do you count them, and how do you get them out when launch day arrives?

What a waitlist actually needs

  • A form. One email field is enough; a name field is a nice-to-have.
  • A store. Somewhere the signups persist — not just an inbox or a spreadsheet tab that gets overwritten.
  • An export. Eventually you need the list in a usable format, ideally CSV, so it opens in any spreadsheet and imports into any email tool.

That's the whole requirement list. There is no user account system, no authentication, no database schema. The moment you reach for a database for a waitlist, you have signed up for migrations, backups and connection strings — for what is essentially one column of email addresses with timestamps.

The form itself

A waitlist form is a plain HTML form. It needs a method, an action, and one field:

<form action="https://your-backend.example/api/submit/waitlist" method="post">
  <input type="email" name="email" required />
  <input type="text" name="website" class="hp" tabindex="-1" autocomplete="off" />
  <button type="submit">Join the waitlist</button>
</form>

Two details matter. First, every field needs a name attribute — that name is how the submission is stored and how it appears in your export. Second, that hidden second field is a honeypot: it is invisible to humans (hide it with CSS or position it off-screen) and bots fill it in. When it comes back non-empty, the backend knows the submitter was a bot and discards the submission silently. It is the single most effective spam defence for a small form, and it costs one field.

Where the emails go

The action URL is the whole backend. A form backend service (FormHook and others do this) receives the standard form POST, stores the submission with a timestamp, and shows it in a dashboard. With FormHook, the endpoint is created the first time a submission arrives, so you can use any key you like — waitlist, early-access, beta — without configuring anything first. Signups appear in the dashboard immediately, newest first.

This is also where spam filtering lives. Besides the honeypot, heuristics flag signups that look automated — throwaway email domains, submissions with many URLs — and mark them as spam in the dashboard rather than deleting them. When you review the list, what you see is mostly real addresses.

Getting the list out

When launch day is close, export the endpoint to CSV. The file opens in any spreadsheet, imports into Mailchimp, Buttondown, or whatever you use to send, and doubles as your record of how many people signed up. Because the export is a standard CSV, you are never locked into the backend you chose — the data moves with you.

A note on consent

You are collecting personal data, so be straight with people: the form should say what the email will be used for (a launch announcement, not a marketing feed), and you should be able to remove someone from the list when they ask. Most regions require telling visitors what you store and why. A single sentence next to the button covers this for most launches.

When this is enough — and when it isn't

A form backend covers the waitlist itself: capture, store, filter, export. It stops being enough when you want accounts, invites, or automated emails — at that point you need a real app, and you'll be glad your waitlist data is a CSV you can import into it.

Want forms without the backend?

FormHook is a form backend for static sites and Jamstack apps: point your form at an endpoint, submissions land in a dashboard, spam is filtered automatically. See the use cases.