Skip to content
All articles
4 min read

An AI request is only the beginning.

Follow a task through authorization, durable execution, usage tracking, and a result the user can return to.

supastack team

Before the model runs

The user supplies a prompt and an alias such as cheap, fast, or smart. The production server checks authentication, workspace ownership, and entitlement before accepting the task. Provider model IDs and secrets remain behind that boundary — the friendly alias is the only model vocabulary the client ever needs, because the mapping to a real provider model is configuration, not contract.

A durable task record gives the request an identity before the background execution begins. That identity connects the submission, the worker, usage records, and the result. It also gives the user a way to recover the work after navigating away.

The ordering matters: expensive work starts only after cheap checks pass. Verifying authentication, ownership, and entitlement before anything is enqueued keeps unauthenticated or unpaid requests from ever reaching a provider — and makes the failure explainable to the user. The AI module guide documents where those checks live; the workspace boundaries post explains why ownership is derived on the server rather than trusted from the client.

Decide whose keys and whose limits

An AI feature is a spending decision. supastack lets workspaces bring their own provider keys — stored encrypted, never exposed to clients — or run on platform keys, and enforces per-workspace budgets against a model price catalog. Whatever your implementation, the questions are the same: who pays, and where is the limit enforced?

Enforcement belongs in the server workflow, not in a browser-side estimate. A budget checked after generation only records overspending; checked before dispatch, it prevents it. Provider key setup covers the configuration side.

Make execution explicit

Trigger.dev runs the ai.generate workflow. The capability-aware router selects a model using configured policy and the request’s requirements. Treat that policy as an operational input: an unavailable alias should not appear as a working choice in the interface.

A network failure during submission can leave the client uncertain about whether work was queued. The production path uses a task-scoped idempotency key and a saved submission so recovery can reuse the original request. Sending a new task after every timeout would risk duplicate work and duplicate cost.

Durability is also what keeps the interface simple: the screen reads task status and renders it rather than orchestrating retries. When generation spans model calls, tool steps, or schedules, the explicit workflow contract — enqueue, status, cancel — is what keeps “in progress” honest.

Name the failure modes

Between request and result there is a specific, finite set of things that go wrong. Design for each by name rather than for “errors” in the abstract — every task should end in an explainable state: queued, running, failed with a reason, or complete with a result. Task recovery is the kit’s reference for the recovery side.

The interface requirement underneath is that no state can lie. A spinner that outlives the work, or a success message for a task that never ran, is a support ticket and a billing dispute waiting to happen.

  • Submission timed out — recover through the saved submission and the task-scoped idempotency key instead of re-queuing.
  • Provider failed mid-task — mark the task failed with a reason the interface can show.
  • Budget exhausted — reject before dispatch, not after the spend.
  • User navigated away — the durable record and recovery URL restore status and result.

Track what happened

Generation produces more than text. The application records usage and a task result, and the interface reads status through the authenticated API. The usage record is what makes the budget enforceable — it is written before the result is returned, not estimated after.

Completion email is a separate step with separate delivery records. A successful model response does not establish that an email was delivered. Keeping those outcomes distinct makes failures easier to explain and retry without rerunning the model unnecessarily.

The result also needs a home the user can return to: a task page, a history list, a recovery URL delivered in that completion email. A generation that exists only in a transient notification is work you will be asked to produce twice.

Verify each boundary

Use deterministic fake adapters to test the application’s decisions first: denied access, disabled aliases, duplicate submissions, result recovery, and generic errors. Those tests should run without provider credentials.

Then use the explicitly opted-in provider smoke process for real integrations. It requires the documented sandbox configuration and approval to make external calls. The distinction keeps ordinary development fast while making production evidence specific and accountable.

Keep that split stable as the product changes: deterministic coverage near every boundary decision, so a provider swap, a router policy change, or a new alias fails a test rather than failing a customer.

Common questions about AI features in SaaS

A few questions come up in every conversation about putting AI behind a paywall.

  • Where should authorization for AI features happen? — Before anything is enqueued: authenticate, resolve the workspace, check the entitlement, then create the task. Checks run after generation only document misuse.
  • Do I need bring-your-own-key support? — If your customers have their own provider relationships, yes: it decides who pays and who owns rate limits. Store keys encrypted and keep them off clients — the AI configuration guide covers the model.
  • How do I keep retries from double-charging? — Scope the idempotency key to the task and reuse the saved submission during recovery, so a timeout cannot create a second billable run.
  • What usage data should I record? — Per task: model, units consumed, cost against the price catalog, and the workspace — enough to enforce budgets and answer spend questions without rerunning jobs.
  • When does generation belong in a background job? — Whenever it can outlive a request. Model latency, retries, and multi-step work argue for durable execution; only instant, cheap calls belong inline.

Frequently asked questions

14 questions

What is supastack?

supastack is a modular foundation for building AI-powered SaaS products. It brings together common infrastructure so you can focus on product-specific features.

Does it support web and mobile?

Yes. supastack includes Next.js and Expo apps as starting points for web and mobile experiences.

What authentication is included?

Better Auth covers email OTP, magic-link, and social sign-in; email/password stays available at the API layer and through the Auth.js credentials engine for products that need it. Personal workspaces are provisioned with the account so product records stay scoped from day one.

How does it support AI?

supastack includes configurable multi-provider AI, usage tracking, budgets, and encrypted bring-your-own-key support.

How are subscriptions handled?

For products built on the kit, Stripe billing, subscriptions, and entitlements form the paid-access foundation. Provider secrets stay server-only.

Where does my product-specific code live?

Product-specific features remain in a separate codebase while the product configures and integrates supastack’s foundation modules.

How does supastack pricing work?

The kit is a one-time purchase with lifetime updates: One Platform at $249 (temporary launch price, $100 off the regular $349) — your pick of Next.js (Web), Expo (iOS & Android), or Tauri (macOS & Windows Desktop) — or the All Platforms Bundle at $499 (temporary launch price, $100 off the regular $599) with every platform and the full monorepo, plus $75 per extra developer seat. No kit subscription. Checkout on this site delivers your license key by email, with repository access via GitHub invite.

How do workspaces scope my data?

User-owned records are scoped by workspaceId. Identity, entitlements, AI usage, billing events, and audit entries stay inside the personal workspace boundary.

How do background jobs work?

Trigger.dev is the explicit job runtime. The JobRunner contract only promises enqueue, status, and cancel—workflow semantics stay Trigger.dev-specific and explicit.

How is email different from outreach?

Transactional email covers product workflows such as completion notices. Cold outreach and campaigns are product concerns outside this kit’s email module.

How do mobile purchases work?

Mobile includes native purchases and restore through RevenueCat, with access verified by your server. Configure the store accounts and complete device testing before release. Web billing remains separate.

Where do AI provider keys live?

Bring-your-own-key credentials are encrypted and stay server-only. Keys are redacted from logs; usage and budgets remain visible at the workspace level.

Which payment methods does checkout accept?

The Stripe-hosted checkout accepts cards and can also offer Alipay and WeChat Pay once those wallets are enabled on the Stripe account — handy for buyers in China. Wallet authorizations confirm asynchronously, so the license page updates as soon as the payment clears.

Can I get a refund?

After you've got access to the repository, supastack is yours forever, so it cannot be refunded. But rest assured, you get the complete source code with lifetime updates to build and ship unlimited products for yourself or clients. You just cannot resell the code or redistribute the repository as a starter kit or template.

EN