# AI SaaS launch checklist

From https://dawloom.com/tools/ai-saas-launch-checklist/ . Sources checked 2026-10-13.
43 checks. 25 are blockers: do not launch until they are done.

## Spend limits and cost alerts

- [ ] Set a hard monthly spend limit on every model provider account. **(blocker)**
  A bug or an abuser can spend a month of budget in an hour. Both Anthropic and OpenAI let you set your own cap below the account limit. Source: Anthropic rate and spend limits, https://platform.claude.com/docs/en/api/rate-limits
- [ ] Use separate keys and workspaces (or projects) for production, staging, and evals, each with its own limit. **(blocker)**
  A runaway eval job should not take production down with it. Anthropic workspaces and OpenAI projects both take their own spend and rate limits. Source: Anthropic rate and spend limits, https://platform.claude.com/docs/en/api/rate-limits
- [ ] Enforce a usage quota per user and per workspace in your own database, checked before each model call. **(blocker)**
  Provider limits protect your account, not your margin. Only your own quota stops one free user from using what ten paying users pay for. Source: OWASP LLM10:2025, https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/
- [ ] Send spend alerts at about 50% and 80% of the monthly budget to a channel someone reads.
  Alerts only help if someone sees them. OpenAI supports spend alerts and email thresholds on the limits page. Source: OpenAI production best practices, https://developers.openai.com/api/docs/guides/production-best-practices
- [ ] Handle the provider spend-cap error as its own case, with a clear message to users and a page to your team. **(blocker)**
  On Anthropic the spend-cap 429 has no retry-after header and retries keep failing until the next month or a higher limit. Check error_code enforced_spend_limit_reached. Source: Anthropic rate and spend limits, https://platform.claude.com/docs/en/api/rate-limits
- [ ] Log input, cached, and output tokens for every call, with user ID, tenant ID, and feature name.
  When the bill jumps, you need to find the heaviest user and feature in one query, not by guessing.
- [ ] Cap input size and max output tokens per feature.
  OWASP lists input size limits as the first defence against unbounded consumption. A pasted 300-page PDF should not reach the model by accident. Source: OWASP LLM10:2025, https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/

## Rate limits and abuse

- [ ] Rate limit every endpoint that calls a model, per user and per IP. **(blocker)**
  OWASP LLM10 says to "apply rate limiting and user quotas to restrict the number of requests a single source entity can make." Source: OWASP LLM10:2025, https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/
- [ ] Rate limit sign-up, login, password reset, and email sending. **(blocker)**
  These are the first endpoints scripts hit. Unlimited sign-ups also mean unlimited free-tier AI usage.
- [ ] Decide what a free account must prove before it can call a model: verified email, CAPTCHA, or a card on file. **(blocker)**
  A free tier with no gate is a free model API for anyone with a script.
- [ ] Put a timeout on every model call and a step limit on every agent loop. **(blocker)**
  OWASP: "Set timeouts and throttle processing for resource-intensive operations." An agent that loops forever bills forever. Source: OWASP LLM10:2025, https://genai.owasp.org/llmrisk/llm102025-unbounded-consumption/
- [ ] Read provider rate-limit headers and back off with jitter, using retry-after when it is sent.
  Anthropic returns retry-after and anthropic-ratelimit-* headers. Retrying at once makes a 429 storm worse. Source: Anthropic rate and spend limits, https://platform.claude.com/docs/en/api/rate-limits
- [ ] Protect the payment form from card testing: Stripe Checkout or Payment Element, login before paying, and limits on cards per account. **(blocker)**
  Stripe says card testers use your publishable key to try stolen cards, and the declines hurt your approval rate after the attack ends. Source: Stripe card testing guide, https://docs.stripe.com/disputes/prevention/card-testing
- [ ] Run long AI jobs on a queue, not inside a web request.
  A queue gives you retries, a concurrency cap, and a place to see stuck work. A held-open request gives you none of those.

## Prompt injection and data safety

- [ ] Give the model only the tools and data the feature needs, scoped to the current user and tenant. **(blocker)**
  OWASP LLM01: "Restrict the model's access privileges to the minimum necessary for its intended operations." Source: OWASP LLM01:2025, https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- [ ] Require a human to approve anything that sends, pays, deletes, or changes another person's data. **(blocker)**
  OWASP: "Implement human-in-the-loop controls for privileged operations." No current method fully prevents prompt injection. Source: OWASP LLM01:2025, https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- [ ] Mark uploaded files, web pages, and emails as untrusted data inside the prompt. **(blocker)**
  OWASP: "Separate and clearly denote untrusted content to limit its influence on user prompts." Source: OWASP LLM01:2025, https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- [ ] Enforce the tenant boundary in the database query, never in the prompt. **(blocker)**
  Injected text can override a prompt instruction. It cannot override a WHERE clause in your query.
- [ ] Keep API keys out of client code and the repo, store them in a secret manager, and set an expiry. **(blocker)**
  OpenAI recommends environment variables or a secret manager, an expiry date on project keys, and regular rotation. Source: OpenAI production best practices, https://developers.openai.com/api/docs/guides/production-best-practices
- [ ] Run moderation on input and output where users can see each other's content.
  OpenAI's moderation endpoint is free and its omni-moderation-latest model takes text and images. Source: OpenAI moderation guide, https://developers.openai.com/api/docs/guides/moderation
- [ ] Read each model provider's data retention and training terms, and name the providers in your privacy policy.
  Business customers will ask. A clear answer before launch saves a lost deal later.

## Evals and output quality

- [ ] Build a set of real inputs with known-good answers, and run it before every release and every prompt change. **(blocker)**
  Without it, a prompt edit that fixes one case can quietly break ten others.
- [ ] Pin a dated model version, and re-run the evals before you switch. **(blocker)**
  An alias that moves to a new model can change outputs, token counts, and cost on a day you did not choose.
- [ ] Add hostile and odd inputs to the eval set: injection attempts, empty input, huge input, other languages.
  Real users and scripts send these in the first week.
- [ ] Validate structured output against a schema before your code uses it. **(blocker)**
  A missing field should become a retry or a clear error, not a crash three steps later.
- [ ] Decide what users see when the model fails or times out: a fallback model, a retry, or a plain message.
  Every provider has outages. A blank screen reads as a broken product.
- [ ] Add a thumbs-down or report button that saves the request ID.
  The best new eval cases come from the outputs users reject.

## Billing and payments

- [ ] Verify Stripe webhook signatures using the raw request body. **(blocker)**
  Stripe: "Without verification, an attacker could send fake webhook events to your endpoint to trigger actions like fulfilling orders, granting account access, or modifying records." Source: Stripe webhooks docs, https://docs.stripe.com/webhooks
- [ ] Dedupe webhook events by event ID, and do not depend on their order. **(blocker)**
  Stripe: "Webhook endpoints might occasionally receive the same event more than once" and it "doesn't guarantee the delivery of events in the order that they're generated." Source: Stripe webhooks docs, https://docs.stripe.com/webhooks
- [ ] Give every usage event an idempotency key, such as your request ID. **(blocker)**
  Your app will retry a failed send. Without a key, the retry bills the customer twice. Source: Stripe meter events docs, https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage-api
- [ ] Test the unhappy paths in test mode: declined renewal, cancel, downgrade while over the new limit, refund.
  Demos only test the happy path. These cases turn into support tickets and disputes.
- [ ] Write down what happens to access when a payment fails, and how long the grace period is.
  If the code and the support reply disagree, you get a dispute.
- [ ] Decide who handles sales tax and VAT before your first sale outside your home country.
  Stripe Tax, a merchant of record, or your accountant can all work. Deciding after the sales come in costs more.

## Monitoring and operations

- [ ] Turn on error tracking for client and server, with alerts that reach a person. **(blocker)**
  Launch week is when you find the bugs. You want to hear about them before users email you.
- [ ] Trace each model call: request ID, model, latency, tokens, cost, user, and tenant. **(blocker)**
  This one log answers "why is it slow", "why is it expensive", and "what did the user see".
- [ ] Run backups and test one restore before launch. **(blocker)**
  Teams often learn a backup is broken on the day they need it. A test restore finds that out early.
- [ ] Add an uptime check that exercises the main AI feature, not just the home page.
  The home page can be up while the model call behind the product fails.
- [ ] Write a one-page runbook: provider outage, spend spike, leaked key.
  At 2 a.m. nobody should have to work out how to rotate a key from scratch.

## Accounts, legal, and launch day

- [ ] Make account deletion and data export work end to end, including stored prompts and files. **(blocker)**
  Users in the EU have a right to erasure under GDPR Article 17. Stored prompts and uploads count. Source: GDPR (EUR-Lex), https://eur-lex.europa.eu/eli/reg/2016/679/oj
- [ ] Publish terms and a privacy policy that name the AI providers that process user data. **(blocker)**
  Users and business buyers read this before they upload anything sensitive.
- [ ] Tell users when they are dealing with AI output, and check if the EU AI Act transparency rules apply to you.
  Clear labels set expectations and cut support tickets about wrong answers.
- [ ] Give new users a sample or demo so they see the AI work before they bring their own data.
  A new user with an empty workspace has nothing to try the AI on.
- [ ] Name who answers the support inbox during launch week, and how fast.
  Early users ask a lot of questions. Someone needs to own the replies.
