Skip to content

Blog

Incident Report: Security Vulnerability in Open SaaS "updateCurrentUser" function

On Feb 12th, 2025, we learned about a security vulnerability in the updateCurrentUser function of our Open SaaS template. Users of apps built with Open SaaS can exploit this vulnerability to edit any field in their own User database record, including fields they weren’t supposed to have write permissions for, like subscriptionPlan and isAdmin.

If you created your app with the Open SaaS template before Feb 14th of ‘25, your app potentially suffers from this vulnerability, and you should apply the fix from this report as soon as possible. Check out vulnerability and fix sections.

The vulnerability does not affect the “vanilla” Wasp apps (Wasp apps not built with Open SaaS template) or those that modified the problematic part of the code enough to eliminate the problem.

Since then we fixed the vulnerability in all the versions of the Open SaaS template, did a coordinated vulnerability disclosure (culminating with this report) with the suggested fix, reviewed all the other templates and example apps of ours for similar security vulnerabilities, analyzed what at the first place enabled such omission to happen on our side, and prepared a plan on how to minimize the chance of similar mistakes happening in the future.

We sincerely apologize for the impact and inconvenience caused by our mistake. Caring about code quality is at the center of our culture here at Wasp, but in this instance, we failed to follow up on our standards. We are deeply disappointed by it and will ensure we learn from it, improve, and regain your trust in the code we ship, especially as Wasp is heading from Beta toward 1.0.

The vulnerability

The vulnerability is caused by the updateCurrentUser function in src/user/operations.ts (or in src/server/actions.ts if you used an older version of Open SaaS):

export const updateCurrentUser: UpdateCurrentUser<Partial<User>, User> = async (user, context) => {
if (!context.user) {
throw new HttpError(401);
}
return context.entities.User.update({
where: {
id: context.user.id,
},
data: user, // <- This is the problem!
});
};

While this Wasp Action correctly allows the user to modify only data in their own User database record, and not of other users, it does also allow them to potentially change ANY of the fields on their own User db model, including fields like credits, subscriptionPlan, and isAdmin, due to data: user line in User.update() call. Particularly troublesome is the ability to set isAdmin to true, as it gives them further privileges they shouldn’t have.

An example of how a bad actor could exploit this is by creating a user account in your app, obtaining their own auth credentials via browser dev tools, and then sending a modified request to the HTTP route of updateCurrentUser Wasp Action with a payload that sets the isAdmin field to true for themselves.

The fix

The fix consists of three main steps:

  1. Refactor updateCurrentUser function to updateCurrentUserLastActiveTimestamp
  2. Implement additional Wasp Action(s) for updating user data if needed
  3. Refactor updateUserById function to updateUserIsAdminById

Refactor updateCurrentUser to updateCurrentUserLastActiveTimestamp

In the Open SaaS template, as it comes when you create a new project with it, the Wasp Action updateCurrentUser isn’t used for anything else but updating the lastActiveTimestamp field on the User model, despite its general nature. Therefore, we recommend the following fix:

  1. Rename the operation updateCurrentUser to updateCurrentUserLastActiveTimestamp. Make sure to update its name in all the places: main.wasp, client code (i.e. src/client/App.tsx), server code (i.e. src/user/operations.ts).

  2. Rewrite the operation updateCurrentUserLastActiveTimestamp in src/user/operations.ts so it receives no arguments and only updates the lastActiveTimestamp field on the User:

    export const updateCurrentUserLastActiveTimestamp: UpdateCurrentUserLastActiveTimestamp<void, User> = async (_args, context) => {
    if (!context.user) {
    throw new HttpError(401);
    }
    return context.entities.User.update({
    where: {
    id: context.user.id,
    },
    data: {
    lastActiveTimestamp: new Date(),
    },
    });
    };

    Notice that also the name of the type of the operation changed, so you will want to update the type import, and we also changed the operation’s Input type to void.

  3. Remove all arguments from the call to updateCurrentUserLastActiveTimestamp in src/client/App.tsx:

    if (today.getTime() - lastSeenAt.getTime() > 5 * 60 * 1000) {
    updateCurrentUserLastActiveTimestamp(); // <- no args anymore
    }

Implement additional Wasp Action(s) for updating user data if needed

If you were using updateCurrentUser in your code beyond just updating lastActiveTimestamp, to allow the user to update some other User fields, we recommend also defining additional, more specialized Wasp Action(s) that will handle this additional usage.

For example, let’s say that in your app you additionally defined fullName and address fields on the User model, and you were using updateCurrentUser to allow the user to update those. In that case, we recommend defining an additional Wasp Action called updateCurrentUserPersonalData. It could look something like this:

export const updateCurrentUserPersonalData: UpdateCurrentUserPersonalData<Pick<User, "fullName" | "address">, User> = async (personalData, context) => {
if (!context.user) {
throw new HttpError(401);
}
// NOTE: This is also a good place to do data validation if you want to.
const fullName = personalData.fullName
const address = personalData.address
return context.entities.User.update({
where: {
id: context.user.id,
},
data: { fullName, address }
});
};

Refactor updateUserById to updateUserIsAdminById

Finally, while not a security vulnerability, we also recommend updating the related Wasp Action, updateUserById (you can find it next to where the updateCurrentUser function was), in a similar fashion, to ensure it can’t do more than we need it to:

  1. Rename from updateUserById to updateUserIsAdminById.
  2. Rewrite updateUserIsAdminById to only allow setting the isAdmin field:
export const updateUserIsAdminById: UpdateUserIsAdminById<{ id: User['id'], isAdmin: User['isAdmin'] }, User> = async ({ id, isAdmin }, context) => {
if (!context.user) {
throw new HttpError(401);
}
if (!context.user.isAdmin) {
throw new HttpError(403);
}
if (id === undefined || isAdmin === undefined) {
throw new HttpError(400);
}
return context.entities.User.update({
where: { id },
data: { isAdmin },
});
};

Notice that we modified the shape of the operation input (now it is { id, isAdmin }), so you will also want to update the calls to this operation accordingly.


Additional reading

This second part of the report is not required reading: all you need to know in order to fix the vulnerability is in the “The vulnerability” and the “The fix” sections. But, if you want to learn more about what caused the vulnerability, how we handled it, and what are we doing to prevent similar mistakes from happening in the future, read on!

Coordinated vulnerability disclosure

The challenging part about handling a security vulnerability like this one is that we have to make the knowledge of it public so that all the people with affected apps learn about it and how to fix it, but then at the same time we are also making that knowledge easily available to any bad actors that might want to try to exploit it.

One of the popular approaches is coordinated vulnerability disclosure and it is also what we chose to follow in this instance. We decided to disclose the vulnerability in stages, with 1-week pauses in between:

  1. Stage 1 (private disclosure): We assembled a list of everybody we knew was building and deploying apps with Wasp / Open SaaS, be it from our community on Discord, from online search, or from interacting with them in the past. We privately reached out to everybody on the list and shared the details of the vulnerability and the fix, while also asking them to keep it confidential till we go public with it.
  2. Stage 2 (community disclosure): About a week later, we shared the details of the vulnerability in our Discord community, while again asking people not to share it publicly till we go public with it.
  3. Stage 3 (public disclosure): Finally, a week after the Stage 2, we shared the vulnerability fully publicly.

How did this happen?

TL;DR: Failure in our code review process.

At Wasp, we care a lot about code quality, the code review process, and software craftsmanship in general. PRs get thoroughly reviewed, we do our best to write Clean Code (with a grain of salt), we think a lot about naming, we produce RFCs for any complex feature, our codebase is strongly typed (Haskell and TypeScript), we keep track of all the issues and ideas publicly on our GitHub to not lose sight of them and to also get community input and be transparent.

Commitment to these practices does get tested regularly: Wasp is moving fast and is changing a lot since it is still pre-1.0, so there is always more tech debt going on than one would like, but we always felt like we managed to stay on the good side of our commitment to these practices: they enable us to be efficient but also to enjoy and be proud of our work.

So what happened then, what enabled this vulnerability in Open SaaS?

Open SaaS started as a one-person experiment, a simple template/boilerplate starter for Wasp, so we didn’t do the usual thorough code reviewing of every PR at the very start but thought we would do it fully later, once it shaped up a bit. Also, it is just a template, not a library/framework, people can read/modify the code as they like.

Open SaaS did shape up, and not only have people started using it, but it really picked up, more than we ever expected, and we were getting a lot of positive and constructive feedback, feature requests, ideas, bug reports, … . We started reviewing all the new code thoroughly, but we still haven’t done the full retroactive review. We have done some of it, for parts of more sensitive modules, and some of it happened naturally through refactoring, but we haven’t done it systematically for the whole codebase. We would discuss during every quarterly planning how we should do it this quarter, but there was always something with a higher priority, especially on the Wasp side, and Open SaaS was doing great, if there was anything serious, we would already know about it, we thought.

And then we learned about a function in our codebase that allows a user to set any data, without runtime validation, as a partial update for their User record in the database. This function was barely even used in the Open SaaS codebase at this point: it was used only to update a single field in the User database model, and even that usage should have been refactored into something better already. This function was an obvious code smell, but we never reviewed it properly.

The fact is, we never should have made Open SaaS publicly available without doing a full code review of it first. Once the code is out there, be it just an example app, a template, or a library, we can’t guess how it or its usage will evolve, or how will our priorities evolve. Once an exception in the (review) process is made, it is much harder to find the time to catch up on it, than if we did it when we should have done it in the first place.

What we are doing to prevent similar mistakes

  • No code/documentation goes public without a thorough review. We have been doing this from the very start for the Wasp framework codebase, but we were more lenient with the templates and example apps. From now on, there will be no exceptions.
  • We checked all our existing templates and example apps for vulnerabilities.
  • We have done a thorough review of the Open SaaS template codebase. We have already merged a lot of code quality improvements based on it, and we are in the process of merging the rest.
  • We will make it harder at the Wasp framework level to make a similar mistake. The mistake of passing unvalidated/unparsed data is too easy to make - we will, latest for Wasp 1.0, enforce runtime data validation in Wasp, for Operations, APIs, and other externally facing methods. We also have good ideas for advanced access control support in Wasp, which should further make it harder to make these kinds of mistakes.

Timeline

What follows is the timeline of the actions we have taken since we learned about the vulnerability, in order to minimize its impact:

  • Feb 12th, 2025 (Wed), 10 pm CET: we learned about the vulnerability (thanks Ivan Vlahov!)
  • Feb 13th (Thu):
    • Made an action plan on how to handle the incident, including how we will execute the coordinated disclosure.
    • Fixed all the versions of the Open SaaS template, to prevent new projects from being affected.
  • Feb 14th (Fri):
    • Wrote the “Incident Notification” document with a detailed explanation of the problem and the suggested fix.
    • Compiled a list of the people we know are deploying Open SaaS / Wasp apps and privately shared the “Incident Notification” document with them, giving them ~ a week of head start before we go more public with the incident.
    • Reviewed all the other Wasp templates and example apps for similar security issues.
    • Started a deep (re)review of all the Open SaaS code (that will continue into the next week).
  • Feb 17th (Mon):
    • Continued deep review of Open SaaS code.
  • Feb 18th (Tue):
    • Continued deep review of Open SaaS code.
    • Finalized first draft of this Incident Report document.
  • Feb 19th (Wed):
    • Continued deep review of Open SaaS code.
  • Feb 20th (Thu):
    • Continued deep review of Open SaaS code.
    • Notified our Discord community about the incident by sharing the “Incident Notification” document with them, giving them a week of head start before we go fully public with the incident.
  • Feb 21st (Fri):
    • Finalized the deep review of the Open SaaS code (while continuing with the code improvements).
  • Feb 26th (Wed):
    • Went public with the incident by publishing and sharing this Incident Report.

From 0 to 400+ Customers: SaaS Growth Hacks from a Serial Founder

Meet Ricardo - he has successfully launched multiple SaaS products, turning his ideas into revenue-generating apps. If you’re looking to build and launch your own product efficiently, we’re about to share some of Ricardo’s key strategies.

He’s a developer with a background in telecom engineering, having held leadership roles at companies like Vodafone and Glovo. But after years of putting fires out in management, he returned to hands-on development, focusing on building apps that solve real problems—fast.

By leveraging Open SaaS, Ricardo was able to ship multiple projects quickly, skipping the usual headaches of setting up authentication, payments, and other things every SaaS needs. In this post, you’ll discover what types of SaaS products he launched and the strategies he used to get them off the ground.

Why Ricardo Chose Open SaaS

When searching for frameworks to kickstart his projects, Ricardo stumbled upon Open SaaS, a 100% free, open-source starter for React & Node.js. and. He was drawn to Open SaaS because of its simplicity, community, and modern tech stack. He also liked the fact that the company had Y Combinator seal of approval.

“The fact that Wasp is low-friction and uses a great stack like Prisma, React, Node.js, and TypeScript—made it stand out. Plus, the community is super helpful. You can get started fast without spending hours on setup.”

Excited reaction gif

What Ricardo loves most:

  • Pre-built Features: Open SaaS relies on Wasp - a full stack framework for React, Node.js and Prisma. The way Wasp handles routes and authentication was a game-changer.

“Just putting routes in main.wasp makes everything super simple. Auth works seamlessly, too.”

  • Focus on Building: By handling repetitive setup tasks like setting up payment integrations or making admin dashboards, Open SaaS allowed Ricardo to focus on core features.
  • Adaptability: regardless of the idea he had - a full-fledged SaaS, or a Google add-on which needed a robust-backend and a dashboard, he was able to build the app with Open SaaS boilerplate starter.

“I didn’t feel limited by the boilerplate—it’s flexible and gets out of the way.”

Ricardo’s Projects Built with Wasp

Ricardo started a few projects with Wasp, while working on the third one he started before discovering Open SaaS.

Article Generator

  • Built in less than 7 days.
  • 40+ paying customers.

This tool simplifies content creation for businesses by generating SEO-friendly blog posts with AI. Article Generator is competing in a crowded market of AI writing tools, where each tool claims that it’s the best one on the market.

Article Generation

Ricardo is using Open SaaS to focus on feature development while testing pricing strategies to differentiate the product from the rest of the market. Integrations with Stripe, Open AI, and similar helped him move faster than he could on his own. His first clients came from Reddit and he has a standard subscription monetization set up.

⭐️ Star the Open SaaS repo and support tools that help you build fast!

Meeting Reminders

  • Bult in less than 7 days.
  • 400+ paying customers.

This tool is a Google Workspace add-on that reduces no-shows by automating pre-meeting reminders. His competitive edge is that he covers WhatsApp alongside SMS and email reminders. Meeting Reminders app shows how versatile Open SaaS boilerplate is, because it can handle edge cases like this one and integrate into Google’s system.

Calls being skipped was a huge pain for Ricardo when he was working at a VC company. His day would include a lot of calls, and the cancellation rate was high. Once he started emailing participants before the call, the number of cancellations reduced significantly. Some time later, he built the tool himself to automate this 😃

Meeting Reminders

In this case, Open SaaS handles backend tasks like subscription checks and authentication. Because of that, this is a lightweight app that solves a niche problem effectively, and doesn’t require a lot of maintenance.

The first users were people he knew personally, and he did a bit of promotion on targeted groups on Slack and Discord. Since it’s a Google Marketplace app, anyone looking for Meeting Reminder add-on will have a chance to see it.

Google Addons

He also relies on SEO, and guess what, he pushed a couple of blog posts with his first SaaS, AI Article Generator. As he said before, you should make tools that scratch your itch first. 😃

Tips for Builders Launching Products

  1. Validate Before You Build

“Start by searching Reddit or similar platforms to find out if people are already solving the problem. If they are, ask yourself: can I do it better or faster?”

Excited reaction gif
  1. Diversify Launch Strategies
  • Avoid relying solely on Product Hunt

“It’s not as effective as it used to be.”

  • Explore short-form content like TikTok for quick validation. You can create a company account and post videos that showcase the problem and the solution.

“Their algorithm is great for targeting the right audience.”

  • Use targeted Reddit ads to reach niche communities.
  1. Start small

“If you’re entering a competitive space, start small. Validate your product’s unique edge by solving specific pain points and adjust based on user feedback.”

  1. Iterate Quickly

“Launch fast, gather feedback, and refine your product. You don’t need to build the perfect app on day one—get it out there, see how people use it, and adjust.”

Ready to Build Your SaaS?

Explore the Open SaaS boilerplate to see how you can kickstart your SaaS today.

⭐️ Star the Open SaaS repo and support tools that help you build fast!

My GPT Wrapper Makes $550 MRR One Year After Launch

Hey builders,

I wanted to share my journey building a micro-SaaS, CoverLetterGPT, which now earns $550/month in recurring revenue (MRR)—all while requiring minimal effort and maintenance. Here’s how I did it and why I believe small, simple SaaS apps are an underrated way to start as an indie maker.

Quick Stats:

  • Built in 1 week
    • using Wasp, a React, NodeJS, & Prisma framework
    • and Chakra UI for the design system.
  • Runs on autopilot
  • ~$550 MRR after one year
  • Minimal customer support—only 3 Stripe disputes to date
  • Costs ~$15/month to operate (hosting + OpenAI API fees)
  • Deployed on Railway & Netlify

BTW, I built Open SaaS, the free, open-source SaaS template based on what I learned from building and launching CoverLetterGPT.

Because Open SaaS is a community-driven project, it also benefits from community feedback and contributions, so it boasts a clean codebase and a ton of useful features. Check it out and give us a star! We’re always improving it.

⭐️ Star the Open SaaS repo and support open-source tools for builders, by builders!

Small Wins Are Worth It

Many developers think a SaaS has to be big, flashy, or wildly profitable to be worth building. I disagree. For me:

  • $550/month is fantastic as side income.
  • It runs itself, requiring virtually no maintenance.
  • I can balance it easily alongside my full-time job.
  • It’s fun and doesn’t consume my free time.
CoverLetterGPT MRR Graph

Here’s why I think you should aim for small, achievable SaaS projects instead of trying to “hit it big” from the start.

Build & Launch Fast

CoverLetterGPT Reddit Post

The most important lesson I’ve learned: speed is everything. The faster you launch, the faster you’ll know if your idea works. Here’s what worked for me:

  1. Avoid long, drawn-out failures: Build small, execute early.
  2. Use the fastest tools available: I used Wasp because it gives me all the building blocks already set up (auth, database, cron jobs, email sending), letting me focus on the business logic of the app. Paired with Chakra UI, I was able to build the app in about 1 week.
  3. Forget perfection: I didn’t worry about making it pretty or perfect—it just had to work.

Keep It Simple

The beauty of micro-SaaS is in its simplicity. Here’s why:

  • My app does one thing well: generating cover letters based on résumés and job descriptions.
  • There’s no need for a fancy landing page or marketing gimmicks. This is my 🌶 hot take.
  • Users get 3 trial credits—enough to try the app and see value before paying.
CoverLetterGPT landing page

One of the biggest perks of micro-SaaS is how low-maintenance it can be. With CoverLetterGPT, I rarely handle customer service thanks to its simplicity.

This means I spend my time on new ideas rather than maintaining old ones.

It’s All About Tradeoffs

While I could optimize and grow CoverLetterGPT further, I’ve chosen to keep it small and simple. For me:

  • Small wins are still wins.
  • I value having a side project that’s easy to manage alongside my full-time job.
  • I’d rather have less stress than chase higher profits.

If you’re thinking about launching your own SaaS, here are some helpful resources:

Final Thoughts

If you’re considering building a SaaS, don’t overthink it. Start small, move fast, and treat it as an experiment. Forget the “rules” and focus on launching. Here’s what matters most:

  • Keep it simple: Build an app that solves one problem well.
  • Launch fast: Test your idea and iterate based on real feedback.
  • Minimize effort: Aim for maximum reward with minimal maintenance.

For me, $550 MRR isn’t just “enough”—it’s amazing. It’s proof that small, focused apps can succeed, and they’re a great way to build confidence and skills as a maker.

Let’s stay in touch!

If you found this helpful, check me out on Twitter where I like to build in public and share what I’m learning and building.


⭐️ Star the Open SaaS repo and support tools that help you build fast!

TurboReel: An Open Source AI Video Generator Built With Open SaaS

Peter is the creator of TurboReel, an open-source platform with a paid SaaS layer, that transforms how creators generate short-form video content. With just a prompt, users can produce polished TikToks and YouTube Shorts in moments.

But like any SaaS founder, Peter faced the challenge of turning his vision into reality without getting bogged down in repetitive technical setup. That’s where Wasp’s Open SaaS boilerplate came in.

In this post, we’ll cover three main things: what inspired Peter to kickstart the project, how he chose the tech stack to build on, and finally, how he made his first $100. Let’s dive in!

Reddit screenshot, 100 users

The Starting Point: Open SaaS Boilerplate

Peter’s journey to Open SaaS began with a simple Google search for SaaS boilerplates.

“I was looking for something that could save me time,” Peter recalls. “I came across a few options—some were free but basic, and others were paid but didn’t feel worth it. Then I found Wasp’s Open SaaS boilerplate.”

What stood out to Peter wasn’t just that it was free, but that it was open source. “I liked the idea of building on something maintained by a community, not locked behind a paywall”, he says. Intrigued, Peter explored Wasp further and discovered an engaging community that offered exactly what he needed to start building TurboReel.

Here’s a video presenting Open SaaS, generated with TurboReel 🐝

TurboReel’s Tech Stack

TurboReel lets users generate short explainer videos with minimal effort. Starting with a single text prompt describing the video’s purpose (e.g. “Create a video on building your SaaS with OpenSaaS”), you can produce professional grade TikTok and YT shorts without needing any video editing skills.

The platform’s open-source foundation unlocks development potential, while the paid SaaS layer helps with funding.

The tech behind TurboReel looks like this:

  • Open SaaS - a free, open-source React & Node.js SaaS starter
    • powered by Wasp, a full stack web framework for JS.
    • Combines React for the frontend and Node.js for backend.
    • Prisma handles the database.
  • OpenAI
    • Used for generating scripts and scenes in the videos.
  • Pollinations
    • Open-source platform for image and text generation.
    • Provides creative assets to enhance video quality.
  • Revideo
    • Library for programmatic video creation.
    • Replaces the previously used MoviePy.

Building faster with Open SaaS boilerplate

“The first thing that impressed me with Open SaaS was how much time it saved, I could start with wasp new saas and immediately have a functioning boilerplate. It gave me the foundation I needed to focus on my product, not the setup.”

The boilerplate included everything he needed:

  • Authentication via email, GitHub and Google
  • Running background jobs via pg-boss
  • Database management
  • Frontend-backend communication via a type-safe RPC layer
  • Deployment of the app with a single CLI command

One feature that particularly stood out was Wasp’s deployment commands.

“Usually, deployment takes time to set up properly, but with Wasp, it was as simple as running wasp deploy fly deploy.”

Here’s what Wasp’s config file looks like, through which you can define full-stack auth in a Wasp app.

Terminal window
app myApp {
wasp: {
version: "^0.15.0"
},
title: "My App",
auth: {
// 1. Specify the User entity
userEntity: User,
methods: {
// 2. Enable Github Auth
gitHub: {},
email: {
// 3. Specify the email from field
fromField: {
name: "My App Postman",
email: "hello@itsme.com"
},
// 4. Specify the email verification and password reset options
emailVerification: {
clientRoute: EmailVerificationRoute
},
passwordReset: {
clientRoute: PasswordResetRoute
},
},
},
onAuthFailedRedirectTo: "/login"
},
}

⭐️ Star Open SaaS repo and support tools that help you build fast!

Out-of-the-box Stripe integration

Another significant advantage for Peter was how Open SaaS handled third-party integrations. Setting up services like Stripe for payments often requires a lot of effort, but Wasp’s OpenSaaS streamlined the process - you just need to add your API key and you’re good to go.

“Payments are usually a huge headache, but Open SaaS made it so smooth. I didn’t have to spend weeks integrating Stripe—it just worked. That gave me more time to focus on TurboReel’s core functionality.

The power of open source

Both TurboReel and Wasp share a commitment to open source.

“The video generation space is complex. There aren’t many established solutions for what I’m trying to do. By making TurboReel open source, I’m inviting smart people to collaborate and help push the project forward.”

Getting first users

Reddit screenshot, 200 upvotes

Peter found interesting subreddits on Reddit and shared his product with users. He enabled everyone to sign up and create a few videos, to get feedback quite early. Lots of people in the creator community loved it, and based off of their feedback, he iterated furthermore improving the UI and the workflow.

Within a few days, he was able to get first paying customers, which proved that his MVP was going in the right direction. Plans for the future? The sky is the limit!

Ready to Build Your SaaS?

Get started with Wasp today, or explore the Open SaaS boilerplate to see how it can work for you.

Should You Use an Open-source SaaS Boilerplate Starter or a $300+ Paid One?

SaaS boilerplate starters became a very popular thing in the web dev community, and also a pathway to a luxury lifestyle for those behind them, sometimes making north of five figure amounts per month.

Twitter screenshot

On the other hand, there’s also been a rise of the open-source SaaS boilerplate starters, that cover various stacks and offer similar features as their paid counterparts, but completely for free and with an active community alongside.

So, what’s the catch? Why pay $300 or $500 for something that you can simply get for free? Are there any trade-offs you should be aware of, and what are the pros and cons of each option?

As it usually turns out in the real world, the answer isn’t completely black and white and depends on what you need (your requirements) but also what you want (your personal preferences).

The goal of this article is to break these further down and give you an objective, simple framework to follow when choosing a boilerplate starter for your next project. So, let’s get into it!

Why a sudden craze with all these starters? SaaS-es are not a new thing at all

We have all been building web apps and SaaS-es for decades, you may rightfully observe, so why this became a thing just now? It seems like everybody is making their own starter today and getting a ton of excitement (and money) from the community.

The answer is that the complexity of building a SaaS (or in another words, a web app) in the last ten years increased tenfold. Partly it is due to the evolution of the underlying architecture (we switched from monolithic, server-based approach to “rich client ↔ backend”) which introduced more moving parts into the equation, and partly due to the explosion of options for each part of the stack.

If you were about to build a SaaS fifteen years ago, you pretty much knew you’d go with either Ruby on Rails, Laravel, or Django, depending on which language and community you preferred. These would come as a batteries-included solution, give you their best defaults and you’d be up and running in a matter of hour(s). You got a single, well-tested path to follow and not much decisions to make.

If you sit down and try to do the same today, your head would probably get dizzy after a few hour(s) of merely reading about all the possible options you could go with:

  • What to use for the frontend? Something mainstream as React, Vue or Angular, or something more sexy and bleeding edge like Svelte or Solid?
  • Should I use a React framework e.g. Next or Remix? Or just go with React + Vite?
  • Do I need SSR and SSG? Or should I just stick with CSR?
  • What should I use as an API layer? Good ol’ REST, or maybe GraphQL, or maybe even typesafe RPC?
  • What to choose for the backend? Do I use something lightweight like Express.js with Node/Bun/Deno or a full-blown solution such as Nest.js/Django/Rails? Or maybe finally try Phoenix/Livewire combo everybody has been talking about? Do I go serverless or not?
  • What about the database and ORM? Relational or non-relational? Should I write raw queries or use a full-blown ORM such as Drizzle and Prisma? If yes, which one?
  • What are my hosting options? Am I going to get locked in with a single provider? What if I want/need to host my app somewhere else?

These are just some of the questions you need to start thinking about when deciding how to start your SaaS in 2024. As you can see, it’s more then enough to make your head spin and even if you’re a seasoned developer and makes you feel like you need to be a rocket scientist to figure out the right combination.

This is why people today turn to SaaS boilerplate starters and gladly even pay for it. It means somebody else did the legwork and (hopefully) made a sensible decision on the stack which will remain current and easy to maintain in the years to come.

Now that we gave some context to the sudden rise of SaaS starters, let’s back to the original question - why pay for something when there is an open-source, free version of it? Let’s take a look at some of the factors that come to play.

With an open-source SaaS starter, you know exactly what you’re getting into

By the definition of open-source, you can see and examine the full code of the starter in advance, before committing to using it for your project.

Although it’s not likely you will go through every line of code beforehand and try to understand it all (that’s why you’re looking for a starter in the first place), you can check it out and see how you like it - e.g. the style of the code, readability and how well documented and tested it is.

You can also see the repository’s activity stats - number of open and closed issues, features in progress, commit frequency and how fast are things being resolved and new features added.

Open SaaS screenshot

Paid, closed-source starters, again by definition, offer at best a fraction of these benefits. You can see the value proposition as the author designed it - some hand-picked testimonials, a demo and potentially have a peek at the docs.

With a paid starter, you become a member of an exclusive tribe (aka Air Jordans Effect)

The most popular paid boilerplates today often come from well-known developers, or “indie makers,” who’ve already built successful products. Buying their boilerplate feels a bit like joining an exclusive club—it’s as if you’re tapping into their expertise and using the same tools they once used to succeed.

Marc promo banner

It’s like wearing a jersey signed by a famous athlete or a perfume co-created by a pop star. It won’t guarantee instant success, but it gives you a sense of connection and inspiration. You’re reminded that someone else turned these same tools into something great—and that you could do it too!

In the long run, this mindset might matter even more than the tools themselves. When things get hard, feeling part of that “club” could be what keeps you going, and taking your idea one step further.

Security: in open-source, everyone is a reviewer

Paid boilerplate starters are mostly an effort of a single person. It is the type of project that, past the initial development phase, doesn’t require a full-time attention and is more of a seasonal nature (e.g. updating libraries to the latest versions). That makes it a perfect workload for a single person and also makes it much more profitable rather than splitting the margin with the team. If there was a whole team behind, it probably wouldn’t cost $500, but rather $2000.

Dave Shipfast tweet

Recently, there was a security incident with one of the popular paid starters that allowed external parties to send unauthorized web hook requests, which caused a lot of ripples in the online community of builders.

It is a good reminder that, while it’s important to ship quickly, security isn’t something that can be skipped over. And while nobody can guarantee the security of any SaaS starter, be it paid or open-source, the fact is that in open-source projects there are much more people involved in both development and code review. Since the code is freely available, you’re also free to review it yourself, use any pen-testing tools on it or ask another expert to check it before committing to it.

With a paid SaaS starter, the bus factor is 1, with open-source you get the full community support!

A paid SaaS starter typically depends on a single maintainer. Since the code is closed source, nobody else has access nor rights to it, and if for any reason the author becomes unable or unwilling to continue working on it, that’s the end of the story. No support, updates, nor anybody to turn to with questions.

On the other hand, an open-source boilerplate starter like Open SaaS is a living organism, with a number of contributors behind it. As with any open-source project, there will typically be a smaller core team which does the bulk of the work and steers the project (and that might as well be a single person in the start), but anybody can join at any point, and they will. As the project grows and becomes more used, more and more people will start adding fixes and features they need themselves and take ownership of the specific parts.

Open source stats from opensaas

Another thing to account for is it takes a long time for SaaS starter business to become more than a side income, and only a fraction of builders will ever come to that point. That means most of boilerplate creators will still have a full-time job or other engagements going on. Which means they will have a limited time for customer support and adding new features.

Open-source SaaS starter === unlimited updates. Closed source? Sometimes.

An another direct benefit of the SaaS starter code being open-source is that you will have an immediate access to all the updates, as soon as they get released. That includes both security patches, version bumps and completely new features.

Commits to open saas

With closed source, it varies a lot from one starter to another. Some offer updates as an upsell (e.g. basic and pro tier), some offer a limited time updates (e.g. 1-year), and some promise a lifetime of updates.

Free updates vs pay for everything

With a paid SaaS starter, you might need to buy a “license” for every new app

Another thing to be aware of is that, with paid starters, there often might be a limit to the number of apps you are allowed to start with a single starter purchase. It is typically phrased in terms of “licenses”, and if you exceed a limit you’re legally required to buy a new one, although you already own the starter code.

Boilerplate licenses

Again, this is not the case with all paid starters (some offer unlimited projects with a single purchase), but it is a common pattern worth checking before buying.

With an open-source starter, there naturally isn’t any such limit - the full source code is publicly available and you’re free to use it in any way you see fit.

With an open-source SaaS starter, you can add new features yourself!

One of the most exciting benefits of the open-source approach is that anybody can contribute! If there is a feature you’re missing or want to improve, you can simply do it yourself it and create a pull request. Then, the core maintainers will review it, give advice and point you in the right direction if needed. Once it gets merged, it is available for everyone to use!

Community contributions

Summary

Now that we have gone through the main differences between open-source and paid SaaS starters, let’s give it a bird’s-eye view:

CostLifetime updatesUnlimited appsMaintainersCommunityAir Jordans EffectEasily contribute
Open-source SaaS starter$0YESYESManyBig, publicRarelyYES
Paid starter$300+DependsDependsTypically oneSometimes, privateOftenNo

This is a useful list to be aware of when making a decision which route to go, but in the end there is no one answer that will fit all. Your decision will depend on what exactly you’re looking to build and which tech stack you prefer using.

Also, the factors above will not be equally weighted by everyone - one person might be excited about being a part of a wider community and being able to easily contribute to the project, while other most appreciate the fact there is a strong online personality they can follow and get inspired.

In the end, the only important thing is to take action and successfully ship that application you’ve been thinking about for so long. Good luck!