GROWTH PATTERN

Adding Freemium Gating to NestJS + PostgreSQL + Stripe Apps

NestJS + PostgreSQL + Stripe subscriptions work, but there's no usage tracking to identify when free users are ready to convert to paid.

NestJS + PostgreSQL + Stripe

Last updated:

What's Missing in Standard NestJS + PostgreSQL + Stripe Architecture

Stripe handles subscription billing perfectly, but it doesn't track usage or enforce feature limits. You'd need to manually check subscription status and implement your own usage tracking in PostgreSQL. Stripe webhooks fire for payment events, but not for usage milestones.

Standard NestJS + PostgreSQL + Stripe Flow vs Optimized Skene Flow

Standard Flow
1

User subscribes via Stripe

2

Subscription status stored in PostgreSQL

3

Features accessible but no usage limits enforced

Skene Flow
1

Track usage in PostgreSQL 'subscriptions' and 'usage' tables

2

Detect when free tier user hits limit (e.g., 100 API calls)

3

Block feature access and trigger upgrade prompt email

4

Track conversion from free to paid

Visual comparison of the flows:

Loading diagram...

How Skene Fixes This

This Skene Prompt installs freemium gating into NestJS + PostgreSQL + Stripe by monitoring PostgreSQL usage tables and Stripe subscription status. When free users hit limits, it automatically blocks features and triggers upgrade prompts.

Implementation Comparison

Using Skene Infrastructure

Install via Prompt

cursor.mdc
@task: Initialize Skene.
@action: Analyze my local code, validating subscription via `npx skene login`, and generate `skene.config.ts` to implement the Freemium Gating pattern for NestJS + PostgreSQL + Stripe.

Copy Skene Prompt for Cursor

Generated skene.config.ts

skene.config.ts
// skene.config.ts - The Automated Way
import { defineLoop } from '@skene/sdk';

export default defineLoop({
  type: 'freemium',
  opinion: 'Enforce usage limits for free tier users and trigger upgrade prompts',
  steps: [
    {
      trigger: {
        type: 'api',
        endpoint: '/api/features/*',
        method: 'POST'
      },
      condition: {
        type: 'usage',
        limit: {
          free: 100,
          paid: Infinity
        },
        period: '30d'
      },
      action: {
        type: 'block',
        message: 'You've reached your free tier limit. Upgrade to continue.',
        upgradePrompt: {
          type: 'email',
          provider: 'resend',
          template: 'upgrade_prompt'
        }
      }
    }
  ],
  recovery: {
    retries: 0 // No retries for blocking actions
  }
});

Frequently asked questions