DEV Community

Cover image for SaaS Economics: Why We Overpaid 10x for Auth and How We Protected the Cloud from Spam
Flude team
Flude team

Posted on Originally published at blog.flude.guide

SaaS Economics: Why We Overpaid 10x for Auth and How We Protected the Cloud from Spam

Having developed the secure cloud worker architecture described in the previous article, we solved the main engineering task—our parser's core was secure. But now we faced a product problem.

Saas Economics Abuse Protection

How could we allow developers to test Flude for free without letting them bankrupt us on GCP Cloud Run bills? Every second of parsing costs real money. We needed a Free-Tier, but with ironclad protection against Abuse loads. And the foundation for this protection became the authentication system.

The Foundation: Choosing an Auth Provider

We needed to manage users, quotas, and B2B organizations. We considered three options: Auth0, Supabase Auth, and Clerk.

Auth0 dropped out first: it lacked a native integration with GitLab, and for our CI tool, GitHub, GitLab, and Bitbucket had to be absolutely equal platforms "out of the box."

That left Supabase Auth and Clerk. According to preliminary calculations for a scale of 100,000 monthly active users (MAU), Supabase would have cost us pennies, while the bill from Clerk would be roughly ten times larger.

And yet, we chose the more expensive Clerk. Why?

First, development savings were the deciding factor. Our future Team pricing plan implied multi-tenancy: the entity of an organization, roles (admin and member), and shared billing. Clerk provided the Organizations feature and ready-made UI components "out of the box"—this fit our model perfectly. With Supabase, we would have had to build a B2B role model from scratch.

Second—architectural purity. Supabase is a full-fledged BaaS with its own PostgreSQL database. Our project was already firmly tied to the Google Cloud stack (specifically, Firestore). Dragging a second DBMS into the project just for cheap authentication would have been a mistake.

In the context of projected revenue, the overpayment for Clerk would amount to only a couple of percent. We consciously traded money for months of saved engineering time.

Defense in Depth (Free-Gate)

Saas Economics Abuse Protection Part 2

Equipped with a powerful identification tool, we started setting limits. Our philosophy during the beta phase was simple: we want to support indie developers and their small Open Source projects, while cutting off giant enterprise mono-repos.

To do this, we built a three-level "gate" that cuts off excess load even before the heavy parsing process starts in the cloud:

  1. Entity Limit: The API token is checked by the server. If a request comes from an account linked to an organization—it is rejected. Free access is open only for personal projects, and support for corporate teams is reserved for future paid plans.
  2. Privacy Limit: We make a cheap preliminary request to the public API (e.g., GitHub) before starting a heavy repository clone. If the code is private—rejection (rejected_private).
  3. Greed Metric (5MB Limit): The most important check happens inside the worker after a shallow clone (git clone --depth 1). We don't trust the repository size from the API (it might contain gigabytes of garbage). We weigh only those files that actually match the include_patterns. If the net volume of code exceeds 5 MB, the worker immediately aborts the job.

Dynamic Rate-Limit and the Window of Loyalty

Saas Economics Abuse Protection Part 3

Even small Open Source projects can trigger CI on every tiny commit 100 times a day. To avoid parsing all of this at our expense, we implemented a dynamic rate-limit based on Firestore.

For new accounts, we open a "window of loyalty": for the first 7 days, we allow up to 5 builds per day so the developer can calmly configure CI and play with the Flude configuration.
But a week later, harsh reality sets in—the limit drops strictly to 1 free build per day. If you want to parse documentation on every PR, you'll have to wait for the launch of paid plans, which we are currently only designing.

As a final chord, we embedded a global "kill switch" in Firestore (system_status/global.enabled), which allows us to disable all free builds with a single button in case of any infrastructure attack.

What's Next?

We designed great business logic protecting our servers from spam and integrated a powerful authorization provider. But, as often happens in the JS ecosystem, third-party dependencies have a habit of suddenly breaking.

The integration of Clerk and the transition to the new Next.js 16 standards turned our frontend development into a real quest with deprecated functions and broken routes. About this (and how a single renamed line broke contracts across the entire distributed system)—in the next episode.


Originally published on our blog: https://blog.flude.guide/blog/saas-economics-abuse-protection

Also read us:

Top comments (0)