Migrating to Stripe Entitlements? Verify your migration is complete.
Stripe Entitlements makes Stripe the source of truth for feature access. The migration is the risky part — you have N users with has_paid_access=true in your DB and need to grant each of them the corresponding Entitlements feature in Stripe. Miss one, and a paying customer loses access. ProdVerdict catches both directions of drift.
Full migration guide — six steps from DB flags to Entitlements as source of truth.
The wedge
Stripe won't build this. We did.
Stripe's interest is adoption — they want you to use Entitlements. They don't want to build a tool that tells you your migration is incomplete. That's ProdVerdict's job. The entitlements-migration contract is a deterministic check that catches four classes of drift during migration.
Check 1
Migration gap
User has has_paid_access=true but no active Entitlements grant in Stripe. High severity. The user paid but Stripe doesn't know.
Check 2
Stale grant
Stripe has an active Entitlements grant but your DB says has_paid_access=false. Medium severity. Either flip the DB flag or revoke the grant.
Check 3
Duplicate grants
Same customer has the same feature granted twice — usually a manual-grant plus subscription-grant collision. Medium severity.
Check 4
Missing customer id
User has has_paid_access=true but no stripe_customer_id. Blocks migration — needs backfill. High severity.
Migration playbook
Six steps from DB flags to Entitlements
Step 1
Define Entitlements products and features in Stripe
Set lookup_key on each feature to match your plan slug (pro, starter). Attach features to products.
Step 2
Add the entitlements-migration contract to prodverdict.yml
Point it at your users table and your Stripe key. One block of YAML.
Step 3
Run the contract to find migration gaps
Every user your DB says is paid but Stripe doesn't know about surfaces as a high-severity finding.
Step 4
Backfill using the JSON output
Pipe --format json into a script that grants entitlements in Stripe for each flagged user.
Step 5
Re-run until it passes
Iterate until zero findings. Then flip your app to read from the Entitlements API.
Step 6
Switch the Access contract to stripe_entitlements source
Verify the steady state on a schedule. Remove the migration contract when you're confident.
Try it
See the engine work on a fixture first
No credentials, no git clone. The bundled demo runs the Access contract against a revenue-leak fixture and shows you what a FAIL looks like.
npx prodverdict@0.13.0 demoThen read the migration guide or the Phase 6 design doc.