Skip to content
tezvyn:

How would you enforce a 3-project freemium limit and handle upgrades?

Source: payproglobal.comMediumHow cards are made

How would you enforce a 3-project freemium limit and handle upgrades?

Tests entitlement and growth tradeoffs. Strong answers use API-level enforcement, atomic checks to prevent concurrent overages, soft upsell prompts preserving context, and async billing webhooks. Red flag: UI checks or limits in the projects table.

What's really being asked

This question evaluates whether you can build a growth-aware entitlement system rather than a simple database check. Interviewers want to see separation of concerns between billing, application logic, and user experience. They are looking for awareness of race conditions, caching strategies, and how engineering decisions directly impact conversion funnels.

The full answer

First, an API-level enforcement layer. The limit must be checked in the backend, ideally behind an entitlement service or middleware that answers whether the user can create a project before the creation endpoint runs. Second, atomicity. A simple SELECT COUNT followed by an INSERT is unsafe under concurrency. Strong answers propose a unique partial index, a compare-and-swap on a counter table, or a serialized transaction so that two simultaneous requests cannot briefly create a fourth and fifth project. Third, UX that preserves momentum. When the user hits the limit, the frontend should receive a specific response code or payload that triggers an upsell modal, preserving any draft project name or configuration so the user does not lose context. Fourth, decoupled billing integration. The upgrade flow should emit a webhook from the payment provider that asynchronously updates the entitlement service. Project creation should not query Stripe or PayPal synchronously. Fifth, state definitions. Clarify whether archived or trashed projects count toward the limit, because that changes the query and the user messaging.

The mistakes people make

Storing the limit as a hardcoded constant in the frontend and disabling the create button there, which is trivially bypassed. Adding an is_paid boolean column directly on the projects table, which couples billing state to application data and breaks when plans change. Returning a generic HTTP 403 with no guidance, which kills conversion. Checking the count in application memory without handling race conditions, leading to silent overages that pollute analytics and support queues.

What usually comes next

How would you handle a team plan where the limit is shared across ten users? What happens if the billing webhook is delayed and the user pays but still sees the limit for thirty seconds? How would you backfill limits for existing users if marketing changes the free tier from three projects to five?

A concrete example

Imagine a user clicks Create Project and the entitlement service returns a payload where allowed is false and reason is project_limit_reached. The frontend opens an upgrade modal pre-filled with the draft project title. The user upgrades. The billing system sends a subscription updated event to a queue. The entitlement worker processes it and writes plan pro and project limit ten to the entitlement cache. The user clicks Create again and succeeds. If two requests arrived at exactly the same moment before the upgrade, the database unique partial index on user_id where status equals active would reject the second insert, returning a clean 409 rather than creating an orphaned record.

Interview question

Which architecture best balances technical correctness and conversion optimization for a 3-project freemium limit?

  • a.Check a cached project count in memory, allow creation if under three, and query the payment provider synchronously during the request
  • b.Store an is_paid boolean on the projects table and use it to bypass the limit check for premium users
  • c.Rely on frontend validation to disable creation and return a generic HTTP 403 when the limit is exceeded
  • d.Use an entitlement service with atomic limit checks, return structured denials to trigger contextual upsell modals, and apply upgrades via async billing webhooksCorrect
Why?

The correct approach separates concerns by using an atomic entitlement service, preserving conversion momentum with contextual upsells, and decoupling billing via async webhooks. Option C is tempting but fundamentally unsafe because frontend checks are easily bypassed and a generic 403 offers no upgrade path.

Just read this? Test yourself on what you have been reading.

Read the original → payproglobal.com

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Every open role lists the topics its interview covers, so you can prepare for the real thing rather than guessing.

See open roles