Engineering

Why static sites still need a backend (just not the kind you think)

February 6, 20266 min read
Why static sites still need a backend

The pitch for static sites is genuinely appealing. Deploy to a CDN, pay almost nothing, get sub-100ms load times globally, never think about server uptime again. For content sites, portfolios, marketing pages, and documentation, this is real and it works.

Then you add a contact form.

Suddenly you're back in familiar territory: a browser needs to send data to something, and that something has to store it, validate it, filter spam, and send an email. None of that can happen in a static HTML file on a CDN.

So did you just smuggle a backend into your "backendless" site? Kind of, yes. But it's more useful to understand what kind of backend, because that changes everything about how you approach it.

What "static site" actually means

A static site is a collection of pre-built files: HTML, CSS, JavaScript, images. When someone visits your site, the CDN serves those files directly. There's no code running on a server to generate the page. No database query, no template rendering, no session lookup.

This is what makes static sites fast and cheap. The CDN has the files cached at the edge, close to the user. Serving a file from disk is orders of magnitude faster than running application code.

But "static" only describes the serving of the site's pages. It says nothing about what happens when a user interacts with it.

The moment static breaks

A static site handles reading just fine. The moment a user needs to write something, you need a server-side component.

Contact forms are the most obvious example. The user fills in their name and message and clicks Send. Where does that go? A static file on a CDN has no ability to receive, store, or forward it.

But contact forms aren't the only example. Here's every interactive feature a site might add that requires some server-side processing:

  • Contact and feedback forms
  • Newsletter subscriptions
  • User accounts and authentication
  • Search (beyond basic in-page text matching)
  • Comments sections
  • Payment processing
  • A/B testing with server-side logic
  • Personalized content based on user state

Every one of these requires something running on a server somewhere. The question is never really "do I need a backend?" It's "who runs that backend for me?"

The four paths forward

When you need to handle form submissions on a static site, you have roughly four options.

Option 1: Do nothing (or use mailto:). Some sites link an email address directly or use a mailto: action. This is a footgun, not a solution. Visitors need a configured desktop email client, you get no record of what was submitted, and it breaks on most mobile devices. Don't do this.

Option 2: Run a traditional backend. A Node.js or Python server that receives form submissions, validates them, stores them, and sends email. You host it on a VPS, a container platform, or a PaaS. This works, but it reintroduces everything you were trying to avoid: servers to maintain, uptime to monitor, infra to scale.

Option 3: Use a serverless function. AWS Lambda, Cloudflare Workers, Vercel Functions, Netlify Functions. Server-side code that runs on demand, without a persistent server. The function wakes up when a submission comes in, handles it, and shuts down. No server to maintain, scales automatically. This is a good option if you want full control, but you still need to handle email sending, spam filtering, storage, and all the complexity that comes with it.

Option 4: Use a form backend service. A hosted service built specifically to receive form submissions. You point your form's action attribute at a URL they provide. They handle storage, spam filtering, email notifications, and rate limiting. You do nothing on the server side.

For most static sites adding a contact form, option 4 is the right starting point. The time investment is minutes, not days, and you get a more complete solution than you'd build yourself in the same timeframe.

The "serverless services" model

Here's a more useful way to think about this: the choice isn't between "static site, no backend" and "traditional site with a server." There's a third model that most modern sites actually use.

You keep your site static and fast. For each capability that requires server-side processing, you use a purpose-built service that handles exactly that thing. Forms go to a form backend. Authentication goes to an auth provider. Search goes to a search service. Email goes to a transactional email API.

Each of those services is someone else's backend, running on their infrastructure, maintained by their team. You pay for the value, not the operations.

This model is sometimes called "headless" or "composable," but those terms get overloaded. The simpler framing: every server-side feature is a service call, and the services you choose determine your total infrastructure footprint.

For a portfolio or marketing site, that footprint might be: form submissions handled by Formtorch, and nothing else. That's genuinely backendless from your perspective. The backend exists, but you don't operate it.

What this means for contact forms specifically

A static site serving HTML pages can have a fully functional contact form without any backend code you write or maintain. The setup looks like this:

<form action="https://formtorch.com/f/YOUR_FORM_ID" method="POST">
  <input name="name" type="text" required />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

That form works on any static site: Astro, Hugo, Jekyll, plain HTML, Next.js static export. No server-side code. No CORS configuration. No email setup. The form endpoint handles all of it.

Spam filtering, email notifications, submission storage, and rate limiting all come with the endpoint. You're not giving up capability by going the static route; you're just choosing where the server-side work happens.

For a complete walkthrough of how this works, see the HTML contact form guide or the Next.js contact form guide if you're working in a React framework.

The complexity you don't see

When you use a hosted form endpoint, what you're actually delegating is a non-trivial engineering problem. There's a post on this blog that maps it out in detail: The hidden complexity of handling form submissions. If you've ever wondered why rolling your own form backend turns into a bigger project than expected, that's the explanation.

The short version: form handling touches CORS, server-side validation, spam scoring, data storage, email delivery, rate limiting, and response handling. Each layer is manageable on its own. Together, they add up to a meaningful maintenance burden.

Static sites are not a compromise

There's sometimes an implication that choosing a static site means accepting limitations. That you're giving up power in exchange for simplicity.

The reality is different. A well-architected static site with the right services can do nearly everything a traditionally-hosted dynamic site can do, with better performance, lower cost, and less operational overhead.

Contact forms are a good example of this. You don't need a database server, an application server, or a mail server to accept form submissions reliably. You need a form endpoint that has all of those things already built. The distinction matters because it changes what "building a site with a contact form" actually requires.

The backend still exists. You just don't have to run it.

Add a contact form to your static site today.

Formtorch works with any HTML or JavaScript framework. No backend code required.

Related posts