Outgrow builder forms

Outgrow builder forms7 min read

Netlify Forms limit: what happens at 100 submissions, and the way out

Legacy Netlify plans meter form submissions per site and upgrade you automatically, and credit plans can pause the site, so move the form to a backend.

Preet SutharFounder, Ikiform

On Netlify's legacy plans, each site includes 100 form submissions a month, and passing that upgrades the site to a paid Forms level automatically. On the credit-based plans for accounts created since September 2025, forms are free, but a free team that runs out of credits has every site paused, forms included. Moving the form to Ikiform means removing the Netlify attributes and setting the action, in plain HTML or any framework.

What's different on Netlify

Netlify isn't a site builder; it's a host with forms built in. That shapes both the limit and the way out. Which limit applies depends on when your account was created:

AccountWhat Netlify's docs sayWhat it means for a busy form
Legacy plans, created before 4 September 2025Forms Level 0 includes 100 submissions and 10 MB of uploads per site per month. Passing it upgrades the site to Forms Level 1, with 1,000 submissions, charged at the end of the billing cycle. Past that, extra usage packages add 500 at a timeA spam wave can move a site to a paid level without anyone deciding to. On the free legacy tier, reaching a limit pauses every site on the account
Credit-based plans, created since thenForm submissions are free and unlimited, with no levelsThe form itself costs nothing. But when a free team uses its monthly credits, Netlify pauses all its projects, and paused projects don't receive form submissions

Netlify's own docs are clear that the legacy upgrade is automatic and that you can't move back down while usage is above the lower level. Check your team's plan type and the site's form usage in the Netlify dashboard before deciding anything.

The second reason people move has nothing to do with numbers. Netlify Forms works by reading your deployed HTML:

  • Forms are found at deploy time. A form rendered by React, Vue or Svelte doesn't exist in that HTML, so you keep a hidden static copy for the build to find, and post to it with a form-name field.
  • With Next.js, the OpenNext adapter needs that copy as a static file in public/, and the post must go to that static file, not to a Next.js page. The build fails if data-netlify appears in React code without one.
  • Submissions must be urlencoded or multipart. JSON isn't accepted.
  • The form only works while the site is deployed on Netlify. Moving hosts means moving forms.
How a legacy Netlify site's form usage climbs in a month, and what posting to Ikiform changesLegacy plan, one site, one monthForm posting to IkiformLevel0100submissionsincludedsubmission101spamcountstooLevel11,000 amonth,billedextrapackages500 moreeachsamepage onNetlifyIkiformendpointplainactionURLNetlifyFormsnothingto countauto-upgradepostHow a legacy Netlify site's form usage climbs in a month, and what posting to Ikiform changesLegacy plan, one site, one monthForm posting to IkiformLevel 0100 submissions includedsubmission 101spam counts tooLevel 11,000 a month, billedextra packages500 more eachsame page on NetlifyIkiform endpointplain action URLNetlify Formsnothing to countauto-upgradepost
  1. On a legacy plan, a site starts the month on Forms Level 0 with 100 submissions included.
  2. Submission 101 arrives. Netlify's usage docs describe the site's usage, so a burst of spam can be what pushes it over.
  3. Netlify upgrades the site to Forms Level 1, with 1,000 submissions, and bills it at the end of the cycle.
  4. Past Level 1, extra usage packages add 500 submissions at a time.
  5. With the form posting to Ikiform, the page still lives on Netlify but the post goes to the Ikiform endpoint.
  6. Netlify Forms never receives the post, so there's nothing for it to count or upgrade.
The hosting stays on Netlify. Only the form's destination moves, and with it the metering.

Move the form, stack by stack

Before you change any code, create one Ikiform form per Netlify form name and set its Honeypot field to bot-field. Then your existing hidden input keeps working as the honeypot, with no rename. Pick your stack:

Plain HTML on Netlify needs the least change. Delete the Netlify attributes and the form-name input, point action at the endpoint, and move the thank-you path into _redirect as a full URL. The bot-field input stays as your honeypot.

<form name="contact" method="POST" action="/thanks" data-netlify="true" netlify-honeypot="bot-field">
  <input type="hidden" name="form-name" value="contact" />
  <p hidden><input name="bot-field" /></p>
  <label>Email <input type="email" name="email" required /></label>
  <label>Topic
    <select name="topic">
      <option value="question">A question</option>
      <option value="bug">Something is broken</option>
      <option value="work">Working together</option>
    </select>
  </label>
  <label>Message <textarea name="message" required></textarea></label>
  <button type="submit">Send</button>
</form>
The TanStack Start and React Router versions post from your server. The server-side versions post with a secret key, so Ikiform skips Allowed domains and its human check. Every post then comes from your server's IP, and the Standard limit of 5 a minute per visitor counts all your visitors together. Choose the Relaxed or Custom rate limit for a form you post through a server, and keep IKIFORM_SECRET_KEY in server-only environment variables.

Every version keeps the same field names Netlify had, so notification emails and CSV columns look familiar. The Netlify Forms comparison has the full attribute mapping, including data-netlify-recaptcha and file inputs.

Deploy previews and allowed domains

Netlify gives every pull request its own address, such as deploy-preview-42--your-site.netlify.app. That isn't a subdomain of your-site.netlify.app, so listing your site's address under Allowed domains doesn't cover previews, and preview posts land in spam with origin_mismatch.

  • Add your-site.netlify.app and your custom domain for production.
  • Add a specific preview host while you test it, then remove it.
  • Don't add netlify.app on its own. Every site on Netlify would be allowed to post to your form.
  • Or point previews at a second Ikiform form with no allowed domains, through an environment variable, and keep production strict.

Cut over without losing submissions

  1. Download each form's past submissions as CSV from the site's Forms section. Ikiform has no import.
  2. Deploy the new form to a preview and send a test. Check field names in the Ikiform dashboard.
  3. Merge to production and send another test from the live domain.
  4. Replace any Netlify outgoing webhook with an Ikiform webhook. Netlify signs with a JWS token; Ikiform uses Standard Webhooks headers, so your verifier changes too.
  5. Once no post has reached Netlify for a few days, turn off form detection in the site's Forms settings.
Netlify accepts file uploads and runs Akismet on every submission. File uploads aren't supported yet. A post with a file gets 422 files_not_supported. If a form needs files, keep that one form on Netlify Forms and move the rest.

Check it works on Netlify

  1. Under the form's Allowed domains, add your site's domain, plus localhost while you develop. Leave it empty to accept posts from anywhere.
  2. Deploy a preview, add its host, and submit the form from it.
  3. Open Submissions in the dashboard. The new submission is there with every field you sent.
  4. Confirm the fields are email, topic and message, with no form-name and no bot-field.
  5. Open the site's Forms tab in Netlify and confirm the test isn't there.
  6. Post once with bot-field filled in. It's stored as spam and sends nothing.
  7. Check the inbox of each notification recipient. Each gets an email with the fields, and Reply goes to the submitter when the form has an email field.

Gotchas

ProblemWhat to do
A form-name field shows up in IkiformThe hidden form-name input is still in the form, or your code still sets it. Remove it; Ikiform identifies the form by the URL.
The Next.js build fails mentioning formsA netlify or data-netlify attribute is still in your React code. Remove it along with public/__forms.html.
Previews post to spamThe preview host isn't on Allowed domains. Add it while you test, or use a second form for previews.
Every post is marked spam, even real onesHoneypot field is still _gotcha while your input is bot-field, or the reverse. Make them match.
422 files_not_supportedThe form has an <input type="file"> with a file chosen. File uploads aren't supported yet; remove the input or ask for a link instead.
429 rate_limitedOne visitor sent more than the form's rate limit allows. Standard allows 5 a minute per visitor. Wait for Retry-After, or choose Relaxed or Custom for forms that post from one shared IP.

Questions

Stuck on a step, or want a guide for your situation? Email hello@ikiform.com.