Back to writing
AI EngineeringAI ImplementationAI StrategyArchitectureProduction AIFrom the Field

You built the feature. You haven't shipped the product.

You built the feature. You haven't shipped the product.
Aug 28, 2026 · 9 min read

I reviewed a codebase a few months back where the core AI feature was genuinely good. Clean model integration, fast responses, a UI the team had put real thought into. They were proud of it, and they had reason to be.

Then I asked some questions.

What happens when the LLM call fails? Who gets alerted if the service goes down at 3 AM? What's the rate limit on the AI endpoint? Has anyone tested the Stripe webhook when a payment fails?

The answers were: "we log something," "we'd notice," "nothing right now," and "not yet."

They were two weeks from launch.

This is the pattern. The feature gets months of attention. Everything around it gets a pre-launch sprint that's supposed to take a week but actually takes a month, except that month doesn't happen because the pressure is on to ship. So things get skipped. Real users find the gaps.

This post is that gap, written out. Not marketing, not GTM, not positioning. Engineering and product only.


CI/CD before anyone touches production

Pushing code directly to a server is a deployment process. It isn't a release process.

That distinction matters when something breaks and you have five minutes before a customer calls.

Before launch: a pipeline that runs tests automatically on every pull request and blocks merge on failure, an automated path from code to staging, a defined process to go from staging to production, and a rollback procedure that doesn't require SSH access or manual commit reverting under pressure.

The rollback test is the one I always ask teams to walk me through. If the answer is more than three steps, or it requires someone to remember commands they don't run regularly, you're not ready.


Structured logs, not print statements

This is what most pre-launch codebases look like:

print(f"Processing request for user {user_id}")
print("Done")

This is what you actually need:

import structlog

log = structlog.get_logger()

log.info("request.started", user_id=user_id, endpoint="/api/generate", plan=user.plan)
log.error("llm.call_failed", user_id=user_id, error=str(e), model="claude-sonnet-4-6", attempt=2)
log.info("request.complete", user_id=user_id, duration_ms=elapsed, tokens_used=usage.total)

The difference is queryability. When something breaks on a Friday night, you need to filter on user_id and see the exact event sequence. Unstructured prints give you a wall of text. Structured logs give you a searchable timeline.

Set up log aggregation before launch. Datadog, Logtail, Papertrail: pick one. The tool matters less than the discipline of making every log line machine-readable.


Error tracking before you have users

In development, errors surface immediately. In production, the user gets a broken screen, closes the tab, and never comes back. You find out three days later when someone emails.

Set up Sentry before launch. Wire it to the backend, the frontend, and any background workers. Configure it to alert on new, previously unseen errors.

The goal is simple: when the first user hits a bug you missed in testing, you know before they have time to open a support ticket.

For AI products, this needs to go beyond HTTP errors. A 200 response doesn't mean the LLM call returned something coherent. Make sure your error tracking can distinguish "the request succeeded" from "the model returned something useful." Silent model failures are harder to catch than exceptions.


Health checks and uptime monitoring

Your service needs a /health endpoint that returns something meaningful, not just a 200:

{
  "status": "ok",
  "db": "connected",
  "llm_api": "reachable",
  "queue": "connected",
  "version": "1.2.0",
  "uptime_seconds": 86400
}

Then point an uptime monitor at it. Better Uptime, UptimeRobot, PagerDuty: the choice matters less than having one. Set up Slack or PagerDuty alerting so you know within minutes when something is wrong.

If you find out your product is down because a user mentioned it on Twitter, you didn't have monitoring. You had infrastructure.


Auth is deeper than login and signup screens

Getting login and signup working is the starting point.

Before a product touches real users, you need email verification on signup (skipping this damages deliverability and lets in garbage accounts), a password reset flow tested end to end including the email actually arriving, OAuth handling if you support it with account-linking edge cases resolved, session expiry with force logout capability, and account deletion that actually deletes everything.

That last one gets deprioritized every time. Build it before launch. GDPR requires it, and it takes longer to build correctly than it looks.


Payment integration is a project

A test charge working in Stripe's sandbox environment is about fifteen percent of what production payment integration involves.

Before launch, you need webhook handling that's idempotent (Stripe will send the same event more than once and your system needs to handle that correctly), a failed payment recovery flow with retry logic and dunning emails, invoice generation, trial period handling including what happens when a trial ends with no payment method on file, plan upgrade and downgrade flows with proration, and a cancellation flow that defines what happens to the user's data and access.

The webhook piece is where most teams carry hidden risk. An event like invoice.payment_failed needs to update the user's subscription status in your database, trigger a retry sequence, and send a notification. If that webhook handler fails silently, you'll have users in billing limbo and no way to find them. Build webhook logging and alerting before you touch live payments.


Transactional email and deliverability

Every product sends email: welcome, password reset, billing notifications, usage alerts. Getting these into the inbox consistently requires more than signing up for an email provider.

Before launch: SPF and DKIM records configured for your sending domain, a DMARC policy published, a custom sending domain (never the provider's default subdomain), bounce and complaint handling wired up, and every transactional email tested end-to-end, including plain text fallbacks.

High complaint rates get your domain blacklisted. Getting off that list is slow and painful. Set up deliverability correctly from the start, and it stays a non-issue.


Product analytics baked in from day one

Vanity metrics (total signups, page views) are easy to add later. Actionable product metrics need to be designed in from the start because they require decisions about what to instrument and why.

Before launch, define the events that tell you whether the product is working:

// The moment a user first gets real value from the product
analytics.track('user.activated', {
  feature: 'first_report_generated',
  plan: 'free',
  days_since_signup: 1
});

// Leading indicator of churn: going quiet
analytics.track('user.idle', {
  days_since_last_session: 7,
  plan: 'pro'
});

// Upgrade intent signal
analytics.track('upgrade.intent_shown', {
  trigger: 'hit_usage_limit',
  plan_from: 'free',
  plan_to: 'pro'
});

// Feature adoption
analytics.track('feature.used', {
  feature_name: 'ai_summary',
  session_count: 3,
  user_id: user.id
});

PostHog, Amplitude, Mixpanel: the tool matters less than the discipline. Without these events instrumented before launch, you'll watch a signup number go up and have no idea whether any of those signups got value before churning.

Google Analytics answers different questions (traffic sources, page views, bounce rate). You need both. They don't substitute for each other.


Signup attribution across the full funnel

You need to know where every signing user came from, and then connect that to whether they converted.

UTM parameters on every external link, captured on the signup event, stored on the user record. Then linked to payment events.

Without this connection, your acquisition data and your revenue data live in separate places with no bridge between them. You end up making marketing decisions based on traffic and pricing decisions based on MRR, with no way to answer the question that actually matters: which channel produces users who pay?


Rate limiting, especially on AI endpoints

Unprotected API endpoints get abused. This is not speculative.

Auth endpoints (login, signup, password reset) need rate limiting before launch. Any endpoint that calls an external LLM or does expensive computation needs it too.

For AI products: per-user token budgets and per-session limits are first-class requirements, not optimizations. Without them, one user on an aggressive loop can generate an invoice that surprises you. I covered the session budget pattern in detail in the production-ready agents post.

Basic bot prevention on signup (to block fake account creation from the start) is also worth doing before you have users, not after your free tier gets abused.


The admin panel nobody builds until something breaks

Every product needs an internal operations view before launch.

At minimum: a list of all users with signup date, plan, and last active timestamp. The ability to look up a specific user's activity history. Subscription status and billing summary per user. A way to extend a trial or adjust a plan without touching the database directly. A link to error tracker filtered to a specific user's sessions.

Without this, every support request turns into a developer opening a database console. That process works for your first ten users and falls apart completely at your hundredth.

This doesn't need to be custom-built. A Retool dashboard or a Metabase read-only view wired to your production database handles most of this in an afternoon.


Activation rate and churn signals

Two metrics most products set up last but should define first.

Activation rate: the percentage of signups who reach the moment the product delivers its first real value. Define that moment before launch. Instrument it explicitly. Track it from day one. If you don't know your activation rate by the end of week two, you don't know whether the product is working for the people who signed up.

Churn signals: behavior patterns that predict a user is about to cancel. Login frequency dropping, feature usage declining, a failed payment, a support ticket that didn't get resolved. These aren't hard to track. They do require deciding upfront what to watch for, which means making those decisions before launch rather than after you notice churn.


Key business metrics you need to bake in, not bolt on

Some metrics are only accurate if you start capturing them from day one. You can't reconstruct historical data you never collected.

Before launch, make sure you have the raw events to calculate: MRR and the components that make it up (new MRR, expansion, contraction, churn), daily and monthly active users, feature adoption rates by plan tier, and time-to-activation by acquisition source.

These don't need a fancy dashboard from the start. They need the underlying events to exist. Build a simple internal metrics page that pulls from your database and update it weekly. When you need a proper dashboard, the data is already there.


Database backups and restore procedures

What happens if your database gets deleted?

Before launch: automated daily backups with off-site storage, and a restore procedure that has been tested in staging. Not documented. Tested, meaning someone actually ran a restore and confirmed it worked and noted how long it took.

Cloud provider infrastructure redundancy is not application-level backup. They solve different failure modes. Both are necessary.


Security (the actual list)

HTTPS is the minimum. These are the rest:

  • HSTS headers enabled so browsers enforce HTTPS
  • Input validation on every API endpoint, server-side (client-side validation is UX, not security)
  • Rate limiting on auth and compute-heavy endpoints
  • Secrets management with nothing hardcoded in code or committed to git
  • Dependency scanning in CI so you're not shipping known vulnerabilities
  • CORS headers set correctly for production domains, not *
  • SQL injection and XSS prevention baked into query and rendering patterns
  • Session expiry and token rotation

For AI products: prompt injection surfaces need explicit attention. If user-supplied text flows into a prompt, that input path is an attack surface. The access control patterns worth building before launch are covered in this post.


SEO before launch, not after

Six months of missed indexing because the sitemap wasn't submitted and meta tags weren't set is six months you don't recover.

Before launch: title and meta description on every page, canonical URLs to avoid duplicate content penalties, a sitemap submitted to Google Search Console, a robots.txt that doesn't accidentally block crawlers, Open Graph tags on pages users will share, and page load performance that won't get you penalized in Core Web Vitals.

This takes a few hours to set up correctly. Skipping it and adding it later means paying for that delay in organic traffic for months.


Privacy policy and terms of service are functional requirements.

If you collect personal data (you do, starting with an email address), you need a privacy policy that accurately describes what you collect and what you do with it. If you operate in Europe, you need a cookie consent mechanism that actually functions correctly and honors opt-out choices.

Cookie banners that don't honor opt-out are both a legal exposure and a trust problem. Build them to work from the start. The template services (Termly, Iubenda) cover most of what early-stage products need without custom legal work.


A written pre-launch checklist

Here's the gap I see most often: none of the above is written down anywhere in the same place.

It lives in people's heads, in scattered notes, or not at all. Nobody has gone through the full list as a team with explicit sign-off before a single real user touches the product.

Make that list. Put every item in it. Assign an owner to each one. Run through it as a team with a definition of done for each item before you announce anything.

Some items will take longer than expected. That's exactly what the exercise is for. It's much better to find that out two weeks before launch than two days after.

Working code is what gets you to the demo. The list above is what gets you to the product.


Found this useful? I do 1:1 sessions on AI, architecture, and strategy. Contact me or send a note to discuss in detail.

Share this post

Found this useful? I do 1:1 sessions on AI architecture and strategy. → Book a session

// stay in the loop

If any of this was useful, there's more where that came from.

I write about agentic systems, LLM infrastructure, and what actually works in production - roughly once or twice a month. No noise, no sponsors.