Do I actually need a backend?
The short answer
You need a backend the moment your app has something shared between users or hidden from them. Accounts, data that outlives the browser tab, secret keys, payment logic: each one needs code and storage that a visitor’s browser can’t be trusted with. If your app has none of that, a single page that shows the same thing to everyone, a static site is enough, and it’s cheaper and simpler to run. In 2026 a backend rarely means a server you rent and babysit. It usually means a hosted database like Supabase plus a few serverless functions that wake up per request and cost nothing while idle. The fastest filter is about money: if a key would let a stranger spend from your account when stolen, it can’t live in the browser, so its calls need a backend. The honest caveat is that your tools may have already handed you a backend without asking, so “do I need one” and “do I already have one” are two different questions.
What “backend” means when you’re vibe coding, not a server in a closet
When your agent says “backend,” picture two things, not a room full of humming machines. The first is a place to keep data that survives after the browser closes, almost always a hosted database someone else runs and patches for you. The second is code that runs on a computer you don’t own, triggered by a request, doing the work a browser shouldn’t: checking a password, charging a card, calling a paid AI model with a key nobody should see.
The split is worth naming because it maps onto a distinction your agent uses constantly. The frontend is everything that runs inside the visitor’s browser, the HTML and the buttons and the JavaScript they can read if they open developer tools. The backend is everything that runs where they can’t look. Anything you ship to a browser, every visitor can read, copy, and replay. That single fact decides most of what follows.
MDN puts the same idea in older words. A static site “returns the same hard coded content from the server whenever a particular resource is requested.” A dynamic site “can generate and return content based on the specific request URL and data.” Storing product data in a database and sending a confirmation email when someone registers are the kinds of tasks MDN uses to show when you cross from the first kind into the second. Serverless functions are just the 2026 way to run that dynamic part: small pieces of code that spin up when a request arrives, run for a second or two, and scale back to zero when nobody’s asking, so an idle app costs nothing.
The one question that settles it: is anything shared or hidden?
Most of the time you can skip the jargon and ask yourself one thing. Does your app have data that’s shared between people, or data that’s hidden from them? If the answer to both is no, you don’t need a backend.
Shared means more than one person touches the same data: a comment others will see, a booking that blocks a time slot for everyone else, a profile that persists between visits. Hidden means there’s something you don’t want the visitor to read or change: another user’s rows, your pricing logic, a secret key. A backend is where shared data lives so everyone sees one consistent copy, and where hidden logic runs so nobody can reach around it. It exposes an API endpoint, a specific address the browser calls to save or fetch, and it decides what each caller is allowed to do.
Walk your app feature by feature. A portfolio, a landing page, a restaurant menu, a tip calculator that does its math in the browser: nothing shared, nothing hidden, so a static site is the right and cheaper answer. A to-do app where your list is yours and has to still be there tomorrow: that’s saved data, so it needs a backend. A booking app where one person’s reservation removes a slot for the next: shared, backend. A contact form that emails you: the sending has to happen somewhere trusted, so that’s a small backend or a form service, even though the rest of the page is static.
The API-key test, and why some keys are allowed in the browser
The confusing part is that some keys are built to be public. Your agent will happily put certain keys straight into frontend code, and that’s correct, which makes “never put keys in the browser” bad advice as stated. The real rule is narrower.
Stripe ships two keys per account. The publishable key (it starts with pk_) is, in Stripe’s words, safe to use outside your backend and is displayed by default because it isn’t confidential. The secret key (sk_) has unrestricted permissions and must stay on a server. Supabase works the same way: its publishable, or anon, key is documented as “safe to expose online: web page, mobile or desktop app, GitHub actions, CLIs, source code,” while the service_role key bypasses every security rule and must never be shipped. A publishable key is deliberately low-privilege. A secret key is the keys to the building.
The test is this: if a stranger copied this key out of your page, could they spend your money or read everyone’s data? Assume they can copy it, because anything sent to a browser can be read. If the answer is yes, that key belongs in environment variables on a server, and its calls need a backend. An OpenAI key fails this test hard, which is why OpenAI tells you to route requests through your own backend rather than embed the key in browser or mobile code; an exposed key there becomes a free AI model billed to your card within minutes.
One honest wrinkle. A publishable key like Supabase’s is only safe because the real gatekeeping happens on Supabase’s servers, through row level security that checks every row against your rules. Turn RLS off and that “safe” public key can suddenly read and write your whole database. Which means a static site talking directly to Supabase isn’t really backend-free. It’s using Supabase’s hosted backend. Often “I don’t need a backend” really means “I’m using someone else’s.”
Your tools may have already made this call for you
Before you decide whether to add a backend, check whether you already have one, because two of the most common vibe-coding tools provision it quietly.
As of July 2026, Lovable’s built-in backend is called Lovable Cloud, and per Lovable’s docs it’s enabled by default for your workspace. It’s built on Supabase’s open-source foundation, and when you ask for a feature that needs one, it provisions a database, authentication, file storage, serverless (edge) functions, and secret storage for you, sometimes automatically and sometimes after a prompt for approval. You can still choose a separate Supabase integration for a new project instead, though Lovable notes that migrating an existing Supabase project into Cloud isn’t supported. Either way, the moment you added login or saved data, you got a backend, whether or not you thought of it that way.
Vercel makes a similar decision through a folder. Any file you drop into an api/ directory becomes a serverless function: put api/hello.ts in your project, export a request handler, and Vercel serves it at /api/hello, scaling it up per request and down to zero when it’s quiet. That’s your hosting platform turning ordinary files into backend endpoints with no server for you to manage. The takeaway is the same for both tools. The real question is often what backend you already have, and whether you understand what it’s doing before you stack more features on it.
A decision table for common app types
| Your app | Shared or hidden data? | Backend? | Why |
|---|---|---|---|
| Portfolio, landing page, docs | Neither | No, static | Same content for every visitor; the browser is enough |
| Menu, brochure, in-browser calculator | Neither | No, static | Nothing is saved, nothing is secret |
| Blog you edit in code | Neither | No, static (SSG) | You rebuild when you write; readers just read |
| Contact form that emails you | The send is trusted | Tiny backend or form service | Something safe must receive and send the message |
| To-do or notes app, single user | Saved data | Yes | Your data has to persist past the tab |
| Anything with logins or accounts | Hidden (passwords, sessions) | Yes | Credentials can’t be verified in the browser |
| Anything that takes payments | Hidden (secret key) | Yes | The Stripe secret key must stay server-side |
| App that calls a paid AI model | Hidden (API key) | Yes | The key can’t be shipped to visitors |
| Comments, multiplayer, bookings | Shared between users | Yes | Many people touch one consistent copy of the data |
If your app only lands in the top rows, you can tell your agent to keep it static and it will be faster, cheaper, and harder to break. The moment a real feature lands in the bottom rows, the backend stops being optional.
How to ask your agent so you get a straight answer
Agents reach for a backend because it’s the safe general-purpose answer, the same way they reach for TypeScript and a database on a blank project. To get past the default, ask a sharper question than “do I need a backend.”
Try this instead: “List every feature in this app that can’t work as a static site, and for each one say exactly why it needs a server.” Now you have a short list you can argue with. If it says “you need a database to store the contact form,” ask whether the form could email you rather than save. If it says “you need authentication,” ask whether the first version needs accounts at all, or whether a single shared link would do. Half the time a feature you didn’t strongly want is the only thing dragging in the backend, and you’d rather ship without it for now.
If you do want the backend, make the agent show its work on the dangerous part: “Which service are we using, Lovable Cloud or a separate Supabase project? Which keys are public and which are secret, and confirm the secret ones live in environment variables and never in the frontend.” A clear answer names the service and separates the keys. A vague answer, or a secret key sitting in browser code, is your signal to slow down before you deploy.
What Glim would tell you
Glimfly is building Glim, a firefly that sits beside your coding agent and explains, in plain language, what just changed. “Backend” is exactly the kind of word that flies past a beginner three times in one session while the agent quietly provisions a database and drops a key somewhere. Glim’s job is to catch that moment and name it: this file just became a serverless function, this key is the public one and it’s fine in the browser, this other key is the secret one and here’s where it went. The habit underneath this guide, knowing whether your app shares or hides anything before you let a tool decide for you, is the habit Glim exists to build. Every term above has a plain-language entry in the dictionary, and if you’d like Glim narrating the next time your agent says “let me add a backend,” the waitlist is open.
People also ask
“I have one page with a contact form. Do I need a backend?”
It depends on where the form's data goes. If it emails you or saves the message somewhere, something has to receive it on a server, so yes, you need a small backend, usually a single serverless function or a hosted form service. If the form only filters or reveals content that's already on the page, the browser handles it and you need nothing. The dividing line is whether the submission has to be stored or sent, not whether a form exists on the screen.
“My agent keeps adding a backend. Can I stop it and ship a static site instead?”
You can, if your app has no accounts, no data shared between visitors, and no secret keys that cost you money when stolen. Tell your agent plainly: this is a static site, no backend, no database, keep everything in the browser. If it pushes back, ask it to name the one feature that forces a server. Often the honest answer is that a specific feature like login or payments forces it, and you get to decide whether you want that feature yet.
“Is it safe to put my Supabase key in a static site with no backend?”
Only the publishable (anon) key, and only with Row Level Security turned on for every table. Supabase designed that key to be public, so it ships safely in browser code. The service_role (secret) key must never appear in a static site, because it bypasses all your security rules. And note that even a static site talking to Supabase is leaning on Supabase's hosted backend, so you never truly escaped having one.
Words from this guide
Frontend vs backend: which half of your app is which?
The frontend is the half of your app that runs in each visitor's browser, everything they see and click; the backend runs on a server you control, where secrets stay hidden and the real rules get enforced.
databasesWhere does your app actually store data? Databases, explained
A database is where your app's information actually lives after you close the tab, organized into tables so it can be found, trusted, and shared by many users at once.
webWhat is a serverless function, and why did Vercel add api/?
A serverless function is backend code you deploy without managing a server; the platform starts an instance to run it only when a request arrives, then can shut it down, and you're billed for the seconds it actually ran.
webWhat is an API endpoint? (the doors your app knocks on)
An API endpoint is a specific URL that, combined with an HTTP method, tells a server to do one exact thing, like fetch a user or create a payment.
filesWhat is an environment variable? (and why your app has a .env file)
An environment variable is a named value your app reads from its surroundings at runtime, instead of having it hardcoded, so secrets and settings can change without touching a line of code.
webWhat is hosting? (where your app actually lives)
Hosting is the always-on computer, somewhere out on the internet, that keeps your app reachable at a URL even after you've closed your laptop.
securityYour API key is exposed: what happens, what to do, how to prevent it
An exposed API key is a secret that leaked somewhere public, and from that moment it works for whoever finds it, not just you.
See this in your own project Glim reads it in plain words.
Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.
Explain my session →