Greta.sh

Implementation worksheet · 5 min read

A Trial Expiration Test Matrix for AI-Built SaaS

Test eight cases before launch: expiry with no card (what locks, what stays readable), expiry with card on file (charge fires once, not twice), conversion mid-trial (no double charge at term end), cancellation mid-trial (access until expiry, then clean lapse), expiry during an active session (in-app state changes without data loss), the day-before warning email (fires once, links to payment), re-registration after expiry (old data policy enforced), and timezone edges (expiry at UTC midnight vs the user's midnight). Make them testable by injecting a clock the test can shift — 'set account trial to expire in 60 seconds' beats waiting 14 days or hand-editing production dates.

Every SaaS ships trial logic; almost none test the expiry side, because waiting out a trial is annoying and shifting dates in production is scary. The result is the classic launch-week ticket: 'my trial ended and my data is gone' — usually not gone, just locked behind a state nobody designed.

Put it into practice

1. Make expiry a designed state, not an absence

Expired-no-card is its own account state with defined behavior per your entitlement table's lapse column: what's read-only, what's exportable, what upgrade restores. If the answer is 'whatever the code happens to do', that's the bug.

2. Inject a shiftable clock

The app reads time from one place, and staging lets you set an account's trial_ends_at to now-plus-a-minute. This single affordance turns all eight cases from 'wait two weeks' into a test suite an afternoon can run.

3. Test the charge path for exactly-once

Card on file + expiry must produce one charge, one receipt, one entitlement flip — including when the expiry job retries after a crash. Idempotency keys on the charge call; the test kills the job mid-run and re-runs it.

4. Test expiry mid-session

A user working at the moment of expiry should hit a save-safe wall: current work preserved, next gated action prompts upgrade. Losing an in-progress form to a plan gate converts a warm lead into a refund story.

5. Verify the warning email fires once

Day-before (or your chosen offset), once per account, with a working payment link — and not for accounts that already converted or cancelled. Duplicate warning emails are the most common cron-retry symptom users actually see.

The eight cases

Copy this structure into your review document and record your observed result for each row.

The eight cases
CaseSetupExpectedVerified
Expiry, no cardtrial ends, no payment methodlapse state per entitlement table
Expiry, card on filetrial ends, card savedone charge, entitlements flip
Convert mid-trialupgrade on day 7paid now; no second charge at term
Cancel mid-trialcancel day 7access to expiry, then clean lapse
Expiry mid-sessionactive session at expirywork saved; next action gated
Warning emailT-1 dayexactly one, correct link
Re-register after expirysame email signs up againdata policy enforced, no free reset
Timezone edgeuser at UTC+13expiry at documented boundary

A failure worth checking

The silent lockout: expiry flips a flag, every route redirects to the pricing page, and the user's data is technically retained but practically unreachable — no export, no read-only view, no message beyond 'upgrade'. Users experience it as data loss, word it as data loss in reviews, and no refund un-writes the review. The lapse column exists so this state is designed, not defaulted.

Common questions

Should trials require a card up front?

It's a conversion trade, not a correctness one — but it changes which test cases dominate: card-up-front makes the exactly-once charge path critical; no-card makes the lapse state critical. Test hardest wherever your choice puts the risk.

How do I test this in an AI-built app?

Same matrix — describe the expiry behavior explicitly when specifying the app (the entitlement table's lapse column is the spec), then run the eight cases against staging with the shifted clock. Generated billing logic tests exactly like hand-written billing logic: deliberately.

Basis and scope

This is a proposed implementation method using illustrative examples, not a measured benchmark or a customer case study. Prepared with AI assistance. Validate product-specific behavior against current documentation and your own test environment.

Continue with Greta.sh

Explore Greta