Skip to main content
Business
August 6, 20267 min read

How Much Does a Custom Web App Cost in 2026? A Developer's Honest Breakdown

What a custom web app really costs, what drives the number up, and the four levers that cut the price without cutting quality — from a developer who quotes fixed prices.

Muhammad Mubashar Shahzad

Founder & lead developer at WebDevStudio — React, TypeScript and MERN

How Much Does a Custom Web App Cost in 2026? A Developer's Honest Breakdown

Nobody wants to be the client who asks “how much does a custom web app cost” and gets back “it depends.” It does depend — but the things it depends on are knowable, and you're entitled to see them before you sign anything. This is how I price work, what pushes a quote from $800 to $5,000, and where you can genuinely save money without ending up with something you'll pay someone else to rebuild in eighteen months.

How much does a custom web app cost? The three price bands

Most custom web projects fall into one of three shapes. These are my own fixed-price bands, and they're the same numbers on my services page.

  • Marketing site — from $300, 2–3 weeks: up to about six pages, React and TypeScript, SEO foundations, a contact form, Core Web Vitals tuned
  • Web application — from $800, 6–10 weeks: a full MERN build, auth and roles, a REST API, a MongoDB schema, an admin dashboard, a deploy pipeline
  • Ongoing partner — from $400 a month, rolling: dedicated hours, features, code review, performance and accessibility audits

The word doing the work in that table is from. A web application with two user roles, one payment provider and a straightforward data model sits near the bottom of its band. The same app with four roles, a booking engine, an approvals workflow and two third-party integrations is a different project with a different number — usually two to four times the starting figure.

The reason I quote a fixed price after a call rather than publishing one number is that the call is where those multipliers get discovered. Anyone who quotes a web application before understanding your data model is guessing, and you'll pay for the guess later as change requests.

What actually drives the price

Five things move a quote more than anything else. Every one of them is something you can describe in a sentence before you talk to a developer.

1. Your permission model

“Users can log in” is cheap. “Admins approve what managers submit, contractors see only their own jobs, and clients see a read-only view” is not. Every distinct role multiplies the number of screens, API guards and test cases.

The cost isn't the login form — that's a few hours. It's that every endpoint and every route now needs to know who's asking:

ts
// One role: this is the whole authorisation story
router.get("/jobs", requireAuth, listJobs);

// Four roles: every endpoint carries policy, and every policy needs testing
router.get(
  "/jobs",
  requireAuth,
  requireRole("admin", "manager", "contractor", "client"),
  scopeToOrg,                      // multi-tenant boundary
  scopeToOwnRecords("contractor"), // contractors see only their own
  listJobs
);

Each of those middlewares is small. What costs money is that they compose across forty endpoints, and getting one wrong is a data leak rather than a bug.

Rule of thumb: each additional role beyond the second adds meaningfully to both build and test time. If two of your roles differ only by one button, make them one role with a flag.

2. Your data model

The number of screens is a poor predictor of cost. The number of relationships is a good one. A flat list of records is quick. Records that belong to organisations, reference each other, and have to stay consistent when one is deleted are where the real engineering sits.

ts
// Cheap: standalone documents
const Enquiry = new Schema({ name: String, email: String, message: String });

// Expensive: this schema implies tenancy rules, cascade behaviour,
// aggregation queries for reporting, and index design for all of it
const Job = new Schema({
  org:        { type: ObjectId, ref: "Org", required: true, index: true },
  site:       { type: ObjectId, ref: "Site", required: true },
  assignedTo: { type: ObjectId, ref: "User" },
  status:     { type: String, enum: ["draft", "scheduled", "in_progress", "complete"] },
  checklist:  [{ label: String, done: Boolean, completedBy: ObjectId }],
});

The second schema is maybe fifteen more lines. It's also several weeks more work, because it brings tenancy isolation, cascade rules on deletion, reporting aggregations and index design along with it.

3. Integrations

Every external system you connect to is a small project of its own: authentication, sandbox testing, error handling, and a plan for what your app does when that system is down. Payments, accounting software, email platforms, calendars, CRMs, SMS providers — each one is real scoped work, not a checkbox.

Stripe Checkout is the cheap end because it hands off the hard parts. A custom subscription billing flow with proration and dunning is at the other end and can rival the cost of the rest of the app.

4. Whether a design already exists

If you arrive with a Figma file, I build it. If you don't, someone has to make hundreds of decisions about type scale, spacing, colour, states and responsive behaviour — and that's design work, priced separately from development in most honest quotes.

Middle path that most of my clients take: start from a well-built component base and customise it. You get a coherent interface without paying for a bespoke design system you don't need yet.

5. What “done” means to you

Done can mean “it works on my laptop.” It can also mean tested, monitored, documented, accessible, and deployed through a pipeline that lets the next developer ship safely. The gap between those two definitions is often 30 to 40 percent of a project's cost, and it's the gap most cheap quotes are hiding in.

Why “how many pages?” is the wrong question

A developer asking how many pages you need is scoping a brochure site. For an application, one screen can be ten times another screen.

Consider a jobs list. Version one:

tsx
export function JobsList({ jobs }: { jobs: Job[] }) {
  return <ul>{jobs.map((j) => <li key={j.id}>{j.title}</li>)}</ul>;
}

Version two is the same screen your users actually asked for — server-side pagination, filters that survive a refresh, sorting, role-aware actions, an empty state, an error state and a loading skeleton:

tsx
export function JobsList() {
  const [params, setParams] = useSearchParams(); // filters live in the URL
  const { data, isLoading, error } = useQuery({
    queryKey: ["jobs", params.toString()],
    queryFn: () => api.jobs.list(params),
    placeholderData: keepPreviousData, // no flash between pages
  });

  if (isLoading) return <TableSkeleton rows={10} />;
  if (error) return <ErrorState onRetry={() => refetch()} />;
  if (!data.items.length) return <EmptyState onCreate={openCreateDialog} />;

  return (
    <>
      <JobFilters value={params} onChange={setParams} />
      <JobTable items={data.items} canEdit={usePermission("jobs:update")} />
      <Pagination page={data.page} total={data.total} onChange={setPage} />
    </>
  );
}

Same page on your sitemap. Roughly ten times the work — and version two is the one that doesn't generate support emails. When you compare two quotes, this is usually where the difference lives. Ask both developers what their version of a list screen includes.

Fixed price or hourly?

I quote fixed price for defined scope, and hourly or monthly for open-ended work. Both are legitimate; they just move the risk to different places.

Fixed price puts the estimation risk on me. You know the number before work starts, which makes it easy to get approved internally. The trade-off is that scope has to be pinned down first, and genuinely new requirements become a change order rather than a conversation.

Hourly or retainer puts the risk on you but keeps you fast. It's the right shape when the destination is still moving — early product work, ongoing iteration, or a backlog that reprioritises every fortnight.

The failure mode to avoid is fixed price with vague scope. That contract makes your developer's interests point the wrong way: every clarification becomes something to argue about instead of something to solve.

What a fair quote includes

Whoever you hire, the deliverable should include all of this. If any line is missing, ask why — the answer tells you a lot:

  • Your repository, in your account, from day one — not handed over at the end
  • A deployment pipeline so the app can be updated after the developer leaves
  • Environment separation — at minimum a staging URL you can click through before anything reaches production
  • A README that lets another developer run the project locally without a phone call
  • Performance and accessibility baselines — green Core Web Vitals and keyboard-navigable interfaces, not as an upsell
  • A defined support window after launch. Mine is 30 days on application projects.

Four ways to cut cost that don't cost you later

Cheap quotes usually save money by removing things from that list. These are the levers that don't:

  • Phase it — ship the one workflow that earns or saves money, then fund phase two from what it returns. Most of the features in an initial spec turn out not to be phase-one features once someone is paying per week for them.
  • Don't build auth from scratch — rolling your own session handling, password reset, MFA and account recovery is weeks of work in a domain where mistakes are expensive. A hosted provider is close to free at your user count.
  • Bring your content — waiting on copy and images is one of the most common causes of a project timeline slipping, and slipped timelines cost money on every pricing model.
  • Consolidate roles and states — every extra role, status and edge case is permanently more code to build, test and maintain. Cutting one role early is usually the cheapest scope reduction available.

Frequently asked questions

A few things clients ask before we start:

Is a freelance developer cheaper than an agency?

Usually, because you're paying for one person's time rather than an account manager, a project manager and a margin on both. The trade-off is capacity: a solo developer has a queue and no bench. For projects at the scale above, that's a fair trade — for a twelve-person, multi-year build, it isn't.

Why do quotes for the same brief vary so much?

Because “the same brief” almost never describes the same finished product. One quote assumes the simple list screen, the other assumes the production one. Compare deliverables, not totals.

What does ongoing maintenance cost?

Budget for it as a real line item — dependency updates, security patches and small fixes don't stop after launch. My retainers start at $400 a month; ad hoc work is also fine if your needs are occasional.

Do you work across time zones?

Yes. Most of my clients are in New Zealand, Cyprus, the EU, the UK and Australia. Calls happen in an overlapping window; everything else runs asynchronously with written daily updates.

Where to start

If you have a project in mind, the most useful thing you can do before talking to anyone is write down three things: who the different types of user are, what the main thing each of them does, and what has to be true on launch day. That single page is enough for me to give you a real number instead of a range.

Book a free 30-minute call and you'll get a fixed written quote — scope and price agreed before any work begins.

Web App Cost
Hiring
React
MERN

Interested in working together on a React or MERN project?

Get in Touch