Journal / SaaS Architecture and Scaling

SaaS Architecture and Scaling

Soft Limits, Hard Limits, and Rate Limiting: A SaaS Survival Guide

Limits protect your product from abuse, misuse, and accidental destruction. Here is how to implement them properly.

Soft Limits, Hard Limits, and Rate Limiting: A SaaS Survival Guide

Limits in SaaS fall into three categories: soft limits that warn users before they are blocked, hard limits that enforce a ceiling absolutely, and rate limits that restrict request frequency to protect system stability. Getting the distinction right matters more than most teams realize. A soft limit on a feature a user depends on degrades into a hard limit without warning. A missing rate limit on a public API endpoint is an invitation to an outage.

What you need to know

  • Soft limits enforce behavior by nudging users toward upgrades; hard limits enforce behavior by blocking it; neither should be applied where the other belongs
  • Rate limiting protects your infrastructure from abuse and runaway clients; it is a separate concern from plan limits
  • The most damaging SaaS failure mode is a limit that is not communicated clearly until the user hits it mid task
  • Rate limits should use a sliding window or token bucket algorithm, not fixed windows, to prevent traffic spikes at window boundaries
  • Every limit should have a monitoring path: alert when users are consistently hitting limits because that is either a pricing signal or an abuse signal

The core argument

The difference between a soft limit and a hard limit is a matter of trust and conversion, not just engineering. A soft limit says: you are approaching the boundary of your plan, here is what happens next, and here is how to avoid the disruption. A hard limit says: you cannot proceed. Both have their place, but using a hard limit where a soft limit belongs creates the specific user experience that generates the most support tickets and the most negative reviews: a user stuck mid task, blocked, confused, and unable to complete something they were already doing.

I designed the limit structure for Nexli's free plan specifically to prevent this. The free tier has a soft limit on the number of active students: when a school approaches 80% of their limit, the admin dashboard shows a persistent banner. At 90%, we show a modal during login. At 100%, we still let them view existing data but block creation of new records. A hard block at 100% with no warning at 80% and 90% would have produced the wrong experience for schools who discovered the limit on the first day of term. Soft limits give users agency; hard limits enforce what simply cannot bend.

Rate limiting is a different problem entirely. It is not about pricing; it is about protecting the system. Without rate limits on the API, a single misconfigured client can generate enough load to affect other tenants. The pattern I use: a conservative limit per IP address for unauthenticated endpoints (a few hundred requests per minute), a higher limit per user for authenticated endpoints (a few thousand requests per minute), and a limit per tenant for operations that touch expensive resources. Rate limit headers (X-RateLimit-Remaining, X-RateLimit-Reset) should be included in every API response so clients can manage their own request rate.

Common mistakes

  1. Hard limiting the API at plan tier without communicating the limit in the API response. If a user's plan allows 10,000 API calls per month and they hit 10,000 on the 15th, the 10,001st call should return a 429 with a message that includes the plan limit and the reset date, not a generic error.

  2. Using a fixed window rate limiter that resets at clean intervals. A fixed window that resets every minute creates a double burst: a client can make the full quota at the end of one window and the full quota at the start of the next, effectively getting double the throughput at window boundaries. Use a sliding window or token bucket instead.

  3. Not distinguishing between limit types in your admin tooling. Customer support should be able to see in one view whether a user is hitting a plan limit or a rate limit. These require different responses: a plan limit is an upgrade conversation; a rate limit is a debugging conversation.

  4. Setting limits too low during beta and not adjusting them. Beta limits are often conservative. Real usage data from beta users is the input that should calibrate the limits for GA. Teams that launch to GA with limits still set for the beta period get complaints from day one.

  5. Not alerting on limit hits. A user who hits a plan limit without upgrading is either unhappy or unaware. Either signal deserves a response. Set up tracking for limit hit events and build a lightweight follow up flow.

Where to start

  1. Inventory every limit in your product. List every place where a user can be blocked (plan limit, rate limit, hard technical limit). For each one, answer: does the user have warning before the block? Is the message helpful? Does it tell them what to do next?

  2. Implement rate limiting at the API gateway or middleware layer. Use Redis as the counter store (it handles atomic increments correctly). The algorithm should be a sliding window or token bucket. Start with conservative limits and loosen them based on real traffic data.

  3. Add limit headers to every API response. X-RateLimit-Limit (the ceiling), X-RateLimit-Remaining (what is left), and X-RateLimit-Reset (when it refills) give clients the information they need to manage their own rate without hitting the limit constantly.

FAQ

Frequently asked

  • What HTTP status code should a rate limit return?
  • Should plan limits and rate limits share the same counter?
  • How do you handle rate limits for users behind shared IPs?
  • What happens when a rate limit is hit by a legitimate, high volume customer?
  • How do you test rate limiting in development?

Author

Why I am the right person for this kind of build

I do not have a degree yet, and for this kind of work I have not needed one. I have shipped Dwarka Bricks, Expert Tutorials, Prominence Football Academy, Velmora, and Nexli. The work is on real URLs, used by real people. Yashveer Singh, founder of Yashveer Labs. If the topic on this page is the one you are facing right now, I have done it for someone else and I can do it for you.

Start the conversation See the work DM on Instagram