Price your idea
← All guides

Updated November 2026 in Build

Serverless functions or a server: what a small product actually needs

Most small products never need a server they manage. This guide covers what serverless functions handle well, where their limits bite, how background and scheduled jobs fit in, and the signs you've outgrown them.

BThe Builder Handbook team12 min read. Every price checked on the provider's own page.
Small switches beside one large block
In this guide
  1. What a function is
  2. Jobs that fit functions well
  3. Background functions for longer jobs
  4. Scheduled functions for timers
  5. Where functions bite
  6. What it costs
  7. Signs you've outgrown functions
  8. Mapping a real product
  9. Habits that keep functions reliable
  10. Where function setups go wrong

When you start building, "where does my backend run?" sounds like a big architectural decision. For most small products it isn't. A front end, a hosted database, a login service and a handful of small functions cover almost everything a $20-a-month product does. The question is knowing which jobs fit that shape and which don't.

What a function is

A function is a file in your project that runs when something happens, usually an incoming request. On Netlify, a web-request function exports a handler that receives a Request and returns a Response[1]. Functions can also react to platform events such as a successful deploy or a form submission[1].

export default async (req) => {
  return new Response("Hello, world!")
}
export const config = { path: "/hello" }

You don't manage a machine, patch an operating system or pay for idle time. The trade-off is that each run is short-lived and starts fresh.

Jobs that fit functions well

JobTypeWhy it fits
Receive a payment webhookRequestShort, triggered by an outside service
Save a form to your databaseRequestValidate, write, respond
Call a third-party API with a secret keyRequestKeeps the key off the browser
Generate a report or exportBackgroundTakes longer than a page load should wait
Send weekly reminder emailsScheduledRuns on a timer, no visitor needed
Clean up old records nightlyScheduledQuick, periodic housekeeping

Background functions for longer jobs

A normal function should answer quickly, because someone is waiting. For work that takes longer, Netlify's background functions return an immediate 202 response and keep running for up to 15 minutes[2]. They're available on the credit-based Free, Personal and Pro plans[2].

Two things to design for:

  • The visitor doesn't get the result directly. Write it to your database or send an email, then let the page check for it.
  • Failures are retried: after one minute, then again two minutes later[2]. Make the job safe to run twice, so a retry doesn't send two emails.

Scheduled functions for timers

Jobs that run on a timer
Jobs that run on a timer

Scheduled functions run on a cron schedule, evaluated in UTC, with shortcuts such as @daily and @hourly; they're available on all Netlify plans[3]. Things worth knowing before you rely on one:

  • They have a 30-second execution limit; longer work should hand off to a background function[3].
  • They run on schedule only on published deploys, not previews or branch deploys[3].
  • They can't be called by URL and don't accept POST data[3].

Hypothetical example

A reminder product sends weekly emails to 4,000 clients. A scheduled function wakes every Thursday, finds who needs a reminder, and hands the list to a background function, which sends in batches and records each send. If it fails halfway and retries, the records stop anyone getting two emails.

Where functions bite

  • CPU and time limits. Image processing, PDF generation and AI calls can be slow. On Cloudflare's free Workers plan, each request gets 10 ms of CPU time[4], which rules out heavier work there.
  • Cold starts. An idle function can take a moment to start. Usually fine; noticeable on rarely used endpoints.
  • Database connections. Many short runs opening database connections can exhaust a database's connection limit. Use your database's connection pooling or HTTP-based client.
  • Persistent connections. Live chat, multiplayer and real-time dashboards need long-lived connections. Netlify points to a separate offering for long-lived backends with WebSockets[1], and many teams use a hosted real-time service instead.

What it costs

Function usage is metered differently by each host: Netlify counts compute at 10 credits per GB-hour and web requests at 2 credits per 10,000[6]; Vercel bills invocations and active CPU beyond Pro's included credit[5]; Cloudflare's paid Workers plan starts at $5 a month with 10 million requests included[4]. For a small product with short functions, the cost is usually small; the risk is a bug that loops. Set alerts. See the hosting comparison.

Signs you've outgrown functions

Functions are enough when

  • Most work finishes in seconds
  • Longer jobs fit in background functions
  • Real-time features come from a hosted service

Even then, you rarely move everything. Keep the front end and simple functions where they are, and add one small server for the job that needs it.

Mapping a real product

Hypothetical example

A receipt-reminder product for bookkeepers, mapped job by job:

JobWhere it runsNotes
Sign-in and sessionsLogin serviceNo code of your own beyond the integration
Dashboard dataDatabase, read from the front end with access rulesRow-level rules keep customers separate
Client uploads a receiptRequest functionChecks the link, stores the file, records it
Payment webhookRequest functionVerifies the signature, updates the plan
Thursday remindersScheduled function, then background functionScheduled job finds who's due; background job sends in batches
Monthly PDF summaryBackground functionGenerates and emails the report

Nothing on that list needs a server you manage. The product runs on a static front end, a hosted database, a login service and five functions.

Habits that keep functions reliable

  • Keep each function small, doing one job. It's easier to test and retry.
  • Make jobs safe to repeat: record what's been done, and check before doing it again.
  • Log one line per run with what happened and how long it took.
  • Put secrets in environment variables, never in the function's code.
  • Time-box external calls, so one slow API doesn't hold up everything.

Where function setups go wrong

  • Doing slow work in a request function while the visitor waits.
  • Non-idempotent jobs that send duplicates when retried.
  • Testing a scheduled job on a preview and assuming it ran.
  • Opening a new database connection per run without pooling.

List every backend job your product does, and put each in one column: request, background or scheduled. If anything doesn't fit, that's the one job to think about a server for.

B
The Builder Handbook teamWe write guides for people building small software alone or in pairs. Every price is checked against the provider's own page. More about us

Sources

Checked 14 November 2026. Numbers in brackets in the text point to these sources.

  1. Netlify docs: Functions overview
  2. Netlify docs: Background Functions
  3. Netlify docs: Scheduled Functions
  4. Cloudflare Workers pricing
  5. Vercel pricing
  6. Netlify pricing
The weekly bill

One product's real costs, every week

What it pays for, what it earns, and the cost that surprised its makers. Plus new guides when they're out.

Free. One email a week. Unsubscribe any time.