How to build a SaaS: the parts, the build order and how to use AI
To build a SaaS, validate one painful problem, then build six parts in order: sign-in, a database that separates each customer's data, the one core feature, subscription billing, transactional email and hosting. Use hosted services for sign-in and payments rather than writing them. AI coding agents can write most of the code, but you must review the security and billing parts yourself.
What does a SaaS actually need to work?
A SaaS is software that customers use over the internet and pay for on a recurring basis. The core feature is the part you invent. The rest is the same in almost every product, and it is where first-time builders lose months. Plan for these six parts and the build stops being mysterious.
| Part | What it must do | Build or buy |
|---|---|---|
| Sign-in | Create accounts, log in, reset passwords | Buy: use a hosted auth service such as Supabase Auth |
| Tenant-safe data | Keep each customer’s data invisible to every other customer | Build, using database rules such as Postgres Row Level Security |
| Core feature | The one job the customer pays for | Build: this is your product |
| Billing | Charge by subscription, record who has paid, let people cancel | Buy: use a payment provider such as Stripe Checkout |
| Send receipts, invites and password resets | Buy: a transactional email service | |
| Hosting | Run the app and the database, with backups | Buy: a platform such as Vercel for a Next.js app |
Of the six, only the core feature is unique to you. If your plan has you writing a login system or handling card numbers yourself, stop and look for a hosted service instead. It is cheaper than an incident.
What should you do before you write any code?
The riskiest question in a SaaS is whether anyone will keep paying, and code cannot answer it, so spend the first week on that. Each has a page of its own:
- Pick a problem that recurs. Subscriptions work when the pain comes back every week or month. How to pick your first SaaS idea gives the filters, and micro SaaS ideas and SaaS examples show what small products look like.
- Validate it with real people. Talk to five of the people who would pay. The validation guide has the questions.
- Decide the price early. It shapes the product. How to price a micro SaaS covers it. A plain example: at an illustrative USD 12 a month, 100 customers is USD 1,200 a month before payment fees and tax.
- Scope one job. Use the MVP scoping guide or the free MVP Scope Planner and write down what version one does not include.
If you have no idea yet, browse the board. Every idea has a generated build prompt, and the developer tools and productivity categories hold many ideas that fit a small subscription product.
Which stack should you choose for a first SaaS?
Choose boring, well-documented tools, because an AI agent writes better code for a stack it has seen many times, and you can find answers when it breaks. One common combination for a solo builder is below. It is a default, not the only right answer.
| Concern | Choice | Why |
|---|---|---|
| App | Next.js, deployed on Vercel | One codebase for pages and server routes; Vercel documents Next.js deployment directly |
| Database and sign-in | Supabase: Postgres plus Auth | Real Postgres, so the data is portable; Auth covers password, magic link, one-time password and social sign-in per its docs |
| Payments | Stripe Checkout and webhooks | A hosted payment page, so card details never touch your server |
| A transactional email service | Receipts and password resets must reach the inbox | |
| Errors | An error-tracking service on day one | You will not see failures that happen while you sleep |
The alternative is an AI app builder such as Lovable, which generates a working app from a prompt. That is quicker to a first version. The trade is less control over the code and the security rules, so check what you can export, and read the comparison of Claude Code, Cursor and Lovable before you commit.
In what order should you build it?
Order matters because later steps depend on earlier ones. Billing before the core feature builds a checkout for a product that does not exist. A feature before tenant-safe data means rewriting every query. Follow this sequence.
- Project skeleton and deploy. Make a blank app, deploy it to a public address and confirm it loads. Every later step ships to this.
- Sign-in. Sign up, log in, log out. Test with two accounts.
- Workspaces and the data model. Create the tables and the access rules in the next section. Prove that account A cannot read account B’s rows.
- The core feature, one screen. The smallest version of the thing customers pay for. Use it yourself for a week.
- Billing. Checkout, a webhook, a cancel button. Test with the provider’s test mode, never real cards.
- Email and errors. Receipts, password resets and error alerts.
- Landing page and legal pages. A page that says who it is for, what it costs, and links a privacy policy and terms.
- Five paying or committed users. Launch to a handful, not the world. See how to launch without an audience.
A fair estimate depends on your hours. As an assumption, 100 hours of focused work for a first version is about ten weeks at 10 hours each week. The time page has a calendar table you can adjust.
How do you keep each customer’s data separate?
This is the part to get right, because a mistake exposes one customer’s data to another. The standard approach for a Postgres database is to give every row a workspace, record who belongs to each workspace and let the database refuse any read that crosses the line. Supabase’s docs on Row Level Security say that a table in an exposed schema without RLS is readable and writable by any role with a grant on it, and that you should enable RLS on every table in an exposed schema.
create table workspaces (
id uuid primary key default gen_random_uuid(),
name text not null check (char_length(name) <= 80),
created_at timestamptz not null default now()
);
create table members (
workspace_id uuid not null references workspaces(id) on delete cascade,
user_id uuid not null references auth.users(id) on delete cascade,
role text not null default 'member' check (role in ('owner', 'member')),
primary key (workspace_id, user_id)
);
create table subscriptions (
workspace_id uuid primary key references workspaces(id) on delete cascade,
stripe_customer_id text unique,
stripe_subscription_id text unique,
status text not null default 'none',
current_period_end timestamptz
);
-- Your product's own table. Every row belongs to a workspace.
create table items (
id uuid primary key default gen_random_uuid(),
workspace_id uuid not null references workspaces(id) on delete cascade,
title text not null check (char_length(title) <= 120),
created_at timestamptz not null default now()
);
alter table workspaces enable row level security;
alter table members enable row level security;
alter table subscriptions enable row level security;
alter table items enable row level security;
create policy "read own memberships" on members
for select to authenticated
using (user_id = (select auth.uid()));
create policy "read own workspaces" on workspaces
for select to authenticated
using (id in (select workspace_id from members where user_id = (select auth.uid())));
create policy "read own subscription" on subscriptions
for select to authenticated
using (workspace_id in (select workspace_id from members where user_id = (select auth.uid())));
create policy "read own items" on items
for select to authenticated
using (workspace_id in (select workspace_id from members where user_id = (select auth.uid())));
-- No insert, update or delete policies on purpose.
-- Writes go through your server code, which checks the caller first.Two design choices are in that template. Reads are open only to members of the workspace, and there are no write policies, so the browser cannot change data directly: every change passes through a route you wrote and can check. The subscriptions table is written only by the billing webhook, never by the client. Ask your agent to write a test that signs in as user A and tries to read user B’s items, and run it after every schema change.
How do you charge for a SaaS?
Use Stripe Checkout in subscription mode, or another provider’s hosted checkout, rather than building a card form. Stripe’s docs describe the flow: your application creates a Checkout Session, which provides a URL that redirects the customer to a Stripe-hosted payment page, and after the transaction a webhook fulfills the order using the checkout.session.completed event. Stripe also documents a customer portal so customers can manage a subscription without you building the screens.
The rule that protects you: grant access from the webhook, not from the page the customer returns to. A customer can close the tab, or visit the success URL by hand. Only the signed webhook proves the payment happened. Stripe’s webhook documentation says the handler should verify the request using the raw body, the Stripe-Signature header and your signing secret, and return a 2xx status quickly before slow work.
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
// The raw body is required for signature verification.
const body = await req.text();
const signature = req.headers.get("stripe-signature");
if (!signature) return new Response("Missing signature", { status: 400 });
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!,
);
} catch {
return new Response("Invalid signature", { status: 400 });
}
if (event.type === "checkout.session.completed") {
const session = event.data.object;
// session.client_reference_id is the workspace id you set when creating
// the Checkout Session. Save the customer and subscription ids to the
// subscriptions table with the service role key, on the server only.
console.log("paid:", session.client_reference_id);
}
return new Response("ok");
}That is a skeleton, not a finished billing system. You still need to handle renewals, failed payments and cancellations by listening to the subscription events described in Stripe’s subscription documentation, and to make the handler safe to run twice, since webhook deliveries can be retried. Keep the secret key and the database service key on the server only. They must never appear in browser code.
How do you build a SaaS with AI?
An AI coding agent can write most of the code for the six parts, and the sequence above gives it a clear order of work. The skill that matters is directing it: a written brief, a rules file it reads every session, small steps and a review after each one. The Claude Code guide and the AI coding agent guide cover the method. Start with a project rules file.
# [Product name] A subscription web app for [customer] to [job]. Next.js, Supabase (Postgres + Auth), Stripe Checkout, deployed on Vercel. ## Commands - Dev server: npm run dev - Tests: npm test - Type check: npx tsc --noEmit ## Rules that must never break - Every table has row level security enabled. New tables ship with their policies in the same migration. - Every row that belongs to a customer has a workspace_id. Never query without scoping by it. - The browser never writes to the database directly. Writes go through server routes that check the caller. - Secrets (Stripe secret key, webhook secret, Supabase service role key) are read from environment variables on the server only. Never expose them to client code or NEXT_PUBLIC_ variables. - Access to paid features is granted only by the Stripe webhook, after verifying its signature. - Validate every input at the boundary with a schema. Enforce the same length limits in the database. ## Process - Plan first: list files and changes, then wait for approval. - One feature per change. Run type check and tests before saying a step is done. - Tell me about any new dependency, permission or environment variable.
Then give it the work one step at a time, using the build order. Ask for the plan, build the step, run it and read the diff. The three places where an agent most often needs a human are the access rules, the webhook and anything involving secrets, which is why the template names them.
If you would rather not build alone, the board runs the other way round too. An idea you have but will never build can be posted for free, with no account, and a builder may pick it up.
Frequently asked questions
How do I build a SaaS from scratch?
Validate one recurring problem with real buyers, then build in order: skeleton and deploy, sign-in, tenant-safe database, the one core feature, subscription billing, email, and a landing page with legal pages. Use hosted services for sign-in and payments instead of writing them yourself.
How do I build a SaaS with AI?
Write a brief and a project rules file, then have an AI coding agent build one step at a time in the order above, reading every diff. Review the access rules, the payment webhook and anything involving secrets yourself, because agents can get those wrong in ways that look fine in a demo.
What tech stack should I use for a SaaS?
A common solo stack is Next.js on Vercel, Supabase for Postgres and sign-in, Stripe Checkout for payments and a transactional email service. It is well documented, which also helps AI agents write correct code. Choose what you can learn quickly rather than what is fashionable.
How long does it take to build a SaaS?
As an assumption, a focused first version of about 100 hours takes roughly ten weeks at 10 hours each week. The core feature often takes less time than sign-in, billing, email and legal pages together. Scope to one job and cut everything else from version one.
How do I handle multiple customers in one SaaS database?
Give every customer-owned row a workspace id, record workspace membership in its own table and use database rules such as Postgres Row Level Security so a query can only return rows from workspaces the user belongs to. Test with two accounts to confirm one cannot read the other’s data.
Can I build a SaaS without coding?
Yes, to a point. AI builders and no-code tools can produce a working app, database and sign-in from prompts. You still need to check the access rules, billing and exports yourself. The no-code guide lists what to check before committing to a platform.
Created with AI assistance and edited for this site. Examples are illustrative and do not represent customer research. About the publisher.