DEV Community

Shahryar Ahmad
Shahryar Ahmad

Posted on • Originally published at shahryarahmad.com

Getting a Flutter app through App Review

Most App Review rejections are not surprises. They come from a small, stable set of guidelines, and nearly all of them are decided by choices you make weeks before you submit — how you gate the paywall, whether an account is required, how you word a subscription screen. Fixing them at submission time is expensive. Designing around them costs nothing.

3.1.1 — anything unlockable has to go through in-app purchase

If your app unlocks digital content or features, the purchase runs through StoreKit. Not Stripe, not a web checkout you deep-link to, and not a discreet link to your website pricing page. This is the single most common rejection I see on apps that already work perfectly.

The failure mode is rarely a deliberate attempt to dodge the commission. It is usually a team that already had a web product with a payment provider wired up, and reused it. Review notices, because reviewers open the paywall.

The part teams miss more often is subtler: you may not steer users toward an external purchase either. A line reading "manage your plan on our website" next to a locked feature is enough to draw a rejection, even when the in-app purchase exists and works.

5.1.1(v) — if you can create an account, you must be able to delete it

Any app that supports account creation must offer account deletion from inside the app, and it must actually delete rather than deactivate. A support email address is not compliant. This one is binary and it is checked.

Build it as a real path: a settings entry, a confirmation, a server-side delete, then sign-out. On a Supabase or Firebase backend, remember that deleting the auth record is not the same as deleting the rows keyed to it. Reviewers do not inspect your database, but users notice, and a half-delete is a data-protection problem regardless of what Review saw.

The cheapest time to build this is when you build sign-in. Retro-fitting deletion into a schema that assumed accounts were permanent is where it turns into a week of work.

4.3 — spam, and why it hits template-built apps hardest

Guideline 4.3 covers apps that duplicate something already on the store, including your own other apps. Ship five apps from one codebase with different colours and names and you are a candidate, regardless of how different they feel to you.

This matters disproportionately for Flutter studios, because sharing a design system and a networking layer across apps is exactly what Flutter is good at. The reuse is legitimate; the problem is when reuse extends to the app's actual purpose.

What survives review is genuine differentiation in what the app does, not in its palette. If two of your apps could be one app with a toggle, Review may well conclude that they should be.

3.1.2 — subscription screens are read closely

A subscription paywall must state, on the screen where the user commits, what they are buying, the price, the billing period, and links to your terms and privacy policy. Missing terms links are one of the easiest rejections to earn and one of the easiest to avoid.

Put those links in the paywall itself. Not in settings, not in the App Store description, not two navigations away. Reviewers look at the purchase screen.

Free trials attract particular attention: if there is a trial, say plainly how long it lasts and what happens when it ends. Wording that leaves a reader unsure whether they are about to be charged is treated as unclear rather than clever.

2.1 — the reviewer must be able to get in

If your app requires sign-in, supply working demo credentials, and check them the day you submit. A large share of "we need more information" responses are simply a reviewer unable to reach the thing they are meant to review.

Add notes explaining anything non-obvious: which flow to follow to see the core feature, whether a backend needs to be live, what the app does with a permission it requests. A reviewer with ten minutes and no context will not discover a feature buried three screens deep.

For anything that depends on a server, make sure it is up during review, and remember that review can happen at any hour in any timezone.

Permissions: ask late, and explain why in your own words

Every NSCamera, NSMicrophone, NSPhotoLibrary and location usage string is read. Generic strings — "we need camera access" — are a common rejection, and they are also bad product design: a permission prompt with no reason attached is the highest-friction moment in a first session.

Write the string as a sentence explaining what the user gets: what the app will do with the camera, in this app, for this feature.

Then ask at the moment the feature is used rather than at launch. Acceptance rates are dramatically better when the request follows an action the user just took, and it removes an entire class of rejection at the same time.

What actually reduces review cycles

Treat the guidelines as design constraints during the build, not a checklist at the end. Every item above is a decision that costs nothing when made early and costs a resubmission cycle — typically several days each — when made late.

The practical routine: build account deletion alongside sign-in; write permission strings when you add the permission; put terms and price on the paywall the first time you build it; and check demo credentials on submission day, every time.

The apps I have taken through review most smoothly were not the ones with the best submission notes. They were the ones where none of this was left to the end.


Originally published at shahryarahmad.com.

Top comments (0)