Skip to main content
Watch: Claude Code Just Killed After Effects

Billing

Owner Bypass for Founder Accounts

Use when a metered SaaS needs founder, team, or demo accounts to run every paid action for free, without scattering internal-account checks across the codebase. Covers an isOwner flag on the balance row, an env-backed owner list, and honoring the bypass inside the atomic debit so no call site has to remember it. Also use when a free account is still being charged, or a bypass was forgotten on a new route. If some accounts must not be billed, use this skill.

billingcreditsownerisownersaas

1 file

Description

Use when a metered SaaS needs founder, team, or demo accounts to run every paid action for free, without scattering internal-account checks across the codebase. Covers an isOwner flag on the balance row, an env-backed owner list, and honoring the bypass inside the atomic debit so no call site has to remember it. Also use when a free account is still being charged, or a bypass was forgotten on a new route. If some accounts must not be billed, use this skill.

Install
SKILL.md

name: owner-bypass-billing description: Use when a metered SaaS needs founder, team, or demo accounts to run every paid action for free, without scattering "if internal" checks across the codebase. Covers an isOwner flag on the balance row, an env-backed owner list, and honoring the bypass inside the atomic debit.

Owner Bypass for Founder Accounts

When to trigger

A credit-metered product where the founder, internal team, or demo accounts must never be charged, but every other user pays normally.

Put the flag on the user, honor it in the debit

Store an isOwner boolean on the balance row and check it inside the deduct function, not at each call site. Every metered action already routes through deduct, so one check there covers the whole app and no feature can forget it.

export async function deduct(clerkId: string, amount: number, reason: string) {
  const info = await getBalance(clerkId);
  if (info.isOwner) return { ok: true, balance: info.balance, owner: true }; // never charged
  // ... atomic conditional decrement for everyone else ...
}

Back the flag with an env list so it survives a fresh row

Keep an OWNER_CLERK_ID env list of ids that are always owners. On balance lookup, if the id is in that list but the stored flag is stale (false), promote the row. This means a founder is free from the very first request, before anyone hand-sets a database flag, and a new environment inherits the bypass from config.

const envOwner = ownerEnvIds().has(clerkId);
if (envOwner && !row.isOwner) await db.update(balances).set({ isOwner: true }).where(eq(balances.clerkId, clerkId));
return { balance: row.balance, isOwner: row.isOwner || envOwner };

Report the bypass, do not hide it

Return an owner: true marker from the debit so the UI can show "free (owner)" and traces can record that no credits were spent. A silent bypass makes it hard to tell a free owner action from a billing bug.

Pitfalls

  • Special-casing owners at each call site (if (user.isOwner) return runAction() sprinkled everywhere) guarantees some path forgets it. Honor the flag once, inside the debit.
  • Hardcoding an owner's id in code ships it to the repo and cannot change per environment. Read the owner list from env and persist the resolved flag.
  • Trusting a client-supplied "I am the owner" claim lets anyone go free. Derive ownership from the authenticated id against the server-side list only.
  • Bypassing the debit but still writing a ledger entry double-counts. On owner bypass, skip both the charge and the ledger row and mark the result as owner.
AI Development Stack

Get Smarter About AI Dev

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.

One email per weekReal code, not theoryFree forever