Tutorial: Credits Management for SaaS

Track, limit, and charge your customers via credits

  • Alexandro Martínez
    Author
    by Alexandro Martínez
    5 months ago
  • Imagine you're building an application where users create Projects, and Tasks. In this tuturial I'll show you how you can limit your users usage on important actions, such as creating a project or a task.

    TLDR: Watch the demo instead.

    Step 1/3) Specify your credits

    Open app/modules/usage/dtos/CreditType.ts and specify the credits name, value, description, and amount.

    export type CreditTypeDto = {
      value: string;
      name: string;
      description: string;
      amount: number;
    };
    export const CreditTypes: CreditTypeDto[] = [
      {
        name: "Project Creation",
        value: "credit-project-creation",
        description: "When you create a new project.",
        amount: 2,
      },
      {
        name: "Task Creation",
        value: "credit-task-creation",
        description: "When you create a new task.",
        amount: 1,
      },
    ] as const;
    
    

    export type CreditType = (typeof CreditTypes)[number]["value"];

    In this case, creating a projects costs 2 credits and creating a tasks costs 1.

    If you create a "credits" feature:

    pricing-plan-credits-feature.png

    ...users will be able to click on credits to get more information at /pricing:

    pricing-credits-info.png

    Step 2/3) Track credits usage

    Use the CreditsServer.create function to track a specific credit usage:

    await CreditsServer.create({
      tenantId,
      userId,
      type: creditType, // "credit-project-creation" or "credit-task-creation"
      objectId: /app/${tenantId}/{createdResourcePath},
    });

    This will be visible at /app/:tenant/settings/credits:

    tenant-credits-usage.png

    Step 3/3) Limit usage

    The easiest way to keep track of credits usage is by creating a feature in your plans named "credits".

    pricing-credits-feature.png

    This way you could now use the getPlanFeatureUsage helper function to get the current user usage.

    const creditsFeature = await getPlanFeatureUsage(tenantId, "credits");
    if (creditsFeature && !creditsFeature.enabled) {
      throw Error(t(creditsFeature.message))
    }

    So when the user has reached the credits limit, they will be restricted:

    limit-reached.png

    Optional) Usage based

    If you want to combine usage based billing with credits, create the units at usageBaseUnits.ts:

    import { UsageBasedUnitDto } from "../dtos/subscriptions/UsageBasedUnitDto";

    export const UNIT_API_CALL: UsageBasedUnitDto = { name: "api", title: "API call", titlePlural: "API calls", };

    export const UNIT_PROJECT_CREDITS: UsageBasedUnitDto = { name: "project-credits", title: "Project", titlePlural: "Projects", };

    export const UNIT_TASK_CREDITS: UsageBasedUnitDto = { name: "task-credits", title: "Task", titlePlural: "Tasks", };

    export const usageBasedUnits = [ UNIT_API_CALL, UNIT_PROJECT_CREDITS, UNIT_TASK_CREDITS, ];

    This will be visible when creating a pricing plan with pricing model "Usage based":

    usage-based-pricing-units.png

    To report stripe about the usage, use the reportUsage function:

    // await CreditsServer.create({ ...
    reportUsage(tenantId, UNIT_PROJECT_CREDITS.name);

    Finally, check your stripe dashboard and make sure your pricing strategy works as expected:

    stripe-usage-based-with-credits.png

    Let me know if you'd like to see another SaaS tutorial!

    We respect your privacy.

    TLDR: We use cookies for language selection, theme, and analytics. Learn more.