Form backend for static and JAMstack sites, with file uploads, an inbox for submissions and forwarding into other tools.
Build me a form backend that replaces Getform: submissions from a static site, files that arrive safely, and forwarding into whatever I use. STACK - Node 20+ with Fastify - SQLite through better-sqlite3, WAL mode - Local disk for uploads, with an S3-compatible target if the volume grows - Caddy in front THE DATA MODEL - forms: id, uid, name, allowed_origins_json, redirect_url, notify_emails_json, max_file_bytes, allowed_mimes_json, is_active - submissions: id, form_id, payload_json, spam_score, status, ip_hash, referrer, country, created_at - files: id, submission_id, field, original_name, path, sha256, mime_detected, bytes, scan_status, scan_result, quarantined, created_at - integrations: id, form_id, kind, config_encrypted, is_active — email, webhook, spreadsheet, chat, automation tool - deliveries: id, submission_id, integration_id, status, attempts, response_excerpt, next_attempt_at, at - Everything stored. A submission is somebody trying to reach you and is never discarded UPLOADS, WHICH IS THE PART A HOMEMADE ENDPOINT SKIPS - Multipart streamed straight to disk with a hard size limit enforced as bytes arrive, not after. Buffering an upload in memory is how one request takes the process down - The type is determined from the file's own content — magic bytes — and compared against what the client claimed. A mismatch is recorded and usually refused - An allow-list of types per form, not a block-list. A block-list is a game you lose - Filenames are never used as paths. Store by hash, keep the original name as a label only, and strip directory components from it before it is ever displayed - Archives refused unless explicitly allowed, and if allowed, checked for expansion ratio and entry count before anything is unpacked - Virus scanning through ClamAV if it is available: the file is quarantined until the scan finishes, and a positive result keeps the row and destroys the file - Images have their EXIF stripped, including the location, before storage. Somebody uploading a photo from a phone is sending you their coordinates without knowing it - Served only through a signed expiring URL, from a path outside the web root, with a content-disposition of attachment and a content type from the detection rather than the claim THE ENDPOINT - POST form-encoded or multipart from a plain HTML form; no JavaScript required - Redirect on success, or JSON if asked for - Origin checked against the allow-list, and everything else recorded and refused - A honeypot field and a signed timing token, both documented in the snippet - Rate limits per address hash and per form FORWARDING - Email with the fields laid out readably, the reply-to set to the submitter, and files as signed links rather than attachments - Webhook with an HMAC signature and a timestamp, retried with backoff and jitter, idempotent by submission id - A spreadsheet appender, a chat message, and a generic HTTP step, each configured per form - Every attempt recorded with its response; a permanent failure lands in a dead-letter list with a one-button replay - Credentials for integrations encrypted at rest with a key from the environment SPAM - Score with reasons, hold above a threshold, never silently drop - A review queue, and releasing a held submission delivers it through the normal path - Optional third-party checking off by default, with the privacy consequence stated THE DASHBOARD - An inbox per form, searchable, with files previewed where it is safe to do so - Export CSV and JSON including file links - The paste-ready HTML snippet for each form - Dark and light OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SMTP_URL, SIGNING_SECRET, SESSION_SECRET, HASH_SALT, CLAMAV_HOST, S3_* - Migrations on boot, each once - A disk watchdog that refuses uploads above a threshold rather than filling the volume, and a retention policy per form with a sweeper that actually deletes - Nightly backup of the database and the file store, restore script - Health endpoint that checks disk, mail and the scanner WHAT MATTERS MOST The upload path. Streaming with a real limit, type from content, storage by hash, EXIF stripped and serving through a signed link — get all five right before anything else, and then try to break it with a file that lies about its type and a zip bomb. Accepting files from strangers is the single most dangerous thing a small server can do. Give me the repository, migrations, .env.example, the HTML snippet, and a README with deploy steps behind Caddy and the security decisions listed.
What you lose
- File uploads with virus scanning and storage, which is the part a home-made endpoint usually skips
- Ready-made forwarding into spreadsheets, chat and automation tools
- Spam filtering maintained across many customers
If you would rather not build
- A serverless function with presigned S3 URLs
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $19/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Why this verdict
our own opinion · changed only by a person
88/100
Verdict yes at 88. The only genuinely risky part is accepting files from strangers, and the prompt spells out the checks that make it safe.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Getform
answered from the record above
Is Getform free?
No — the plan we track is $19 a month. Basic at $19/month billed monthly, around $15 annually, for 5,000 submissions.
Can you replace Getform by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 88 out of 100, build time one session. Read what you lose before you decide.
How much does Getform cost?
$19 a month on Basic — $228 a year. Recorded 9 Aug 2026.
What do you lose by replacing Getform?
File uploads with virus scanning and storage, which is the part a home-made endpoint usually skips; Ready-made forwarding into spreadsheets, chat and automation tools; Spam filtering maintained across many customers. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Getform?
Yes: Formbricks, Uppy. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

