Build1 publisher3 min readPublished
Shipping from a new personal Play account starts with 14 continuous days of closed testing
A developer's account of shipping his first app to Google Play and the App Store puts numbers on the queues, starting with 14 continuous days of closed testing he says cannot be shortened. The API access page every guide cites is gone.
The Engineer · Build desk

What happened
- The developer says a new personal Play account has to run a closed test with real testers for 14 continuous days before it can ship to production, and he found out well after he thought he was nearly done.
- Every guide points to Play Console, Setup, API access, and he says that page is gone for newer accounts; he lost an afternoon convinced he was missing a permission.
- Until the App Store Connect step reads Active, subscription products sit in "Missing Metadata", the purchase SDK sees an empty catalogue and the paywall throws "no offerings available".
- iOS exposes a flat product identifier and Android exposes subscriptionId:basePlanId, so the same monthly plan arrives as pro_monthly on one store and pro:monthly on the other.
- Under the Digital Services Act, anyone selling a paid app or in-app purchase in the EU must declare trader status and publish contact details, and Apple pulled thousands of live apps when the deadline passed.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint The 14 days run on calendar time, so the earliest Android production date is fixed the day the closed test opens, and finished code does not move it forward.
- decision Anyone wiring upload automation on a recently created account has to build against the service-account invite and treat the older API access walkthroughs as stale.
- exposure A sole trader who declares EU trader status publishes a personal address on a public listing, so the business-address decision has to be made before submission.
- cost An entitlement webhook nobody monitors puts the cost on the paying user, who is charged by the store and then refused by the server.
The two consoles are joined by an email address. The path the developer describes has four steps: create a Google Cloud project, enable the Play Developer APIs, create a service account, then open Play Console under Users and permissions and invite the service account's address as if it were a colleague [6]. What links the two sides is that email, not the project [7]. Permissions then take up to 36 hours to propagate, which puts this at the start of a launch [8].
Three of the waits come with an upper bound: the 14 days of closed testing, the 36 hours of permission propagation, and up to 24 hours for the tax forms and bank details to read Active in App Store Connect [10]. Run at their maxima and back to back, they come to 16.5 days [24]. He says everything other than the closed test can run in parallel [4]. The floor is then the 14 days, and only if the service account and the Apple paperwork are both started on day one of the test.
For the 14-day figure to apply, the account has to be a new personal Play account [2]. This is one developer's writeup of one app, published on dev.to, and it does not quote the policy text behind any of the waits [25]. Of the last mile he wrote that "almost none of it was written down anywhere I could find" [23]. Of the closed test: "You can't shorten it and you can't skip it." [3]
His first real test purchase went through. Play charged the test card, the app unlocked, and the confirmation screen said "Elite Unlocked" [14]. The backend still had the user on the free tier, so every server-gated feature returned 403 [14]. The cause was one unset environment variable, and the webhook endpoint had been returning 500 the whole time with nobody watching [15]. He also recommends testing expiry, on the grounds that everyone tests the upgrade and almost nobody tests the downgrade [26].
The identifier bug is the one to copy into a checklist. He was matching purchases on the raw store product ID, which passed on iOS and would never have matched on Android, and he caught it by accident before shipping [12]. With a layer like RevenueCat, the match belongs on the package identifier, $rc_monthly. "That's the entire reason the abstraction exists," he wrote [13].
Apple requires that an app which lets users create accounts also lets them delete those accounts from inside the app, auth user and database rows included, and Google does not enforce this nearly as hard, so an Android-first build meets the rule at Apple review [16]. Order matters. Delete the database rows before the auth user, because deleting the auth user invalidates the session immediately, and warn users that deleting the account does not stop the store billing them [17].
The build failures were cheaper. package-lock.json was in .gitignore, and cloud builds run npm ci, which refuses to proceed when the lockfile is missing or has drifted from package.json; locally, npm install never complained [20]. node_modules was ignored as well but had been force-added earlier, so 63,235 files were staged for commit [21]. The emulator that hung on an infinite spinner had lost DNS after the laptop moved from Wi-Fi to a phone hotspot, because it captures its network config at boot and never re-reads it; one line in adb logcat said "Unable to resolve host" [22].
What to watch
- Whether Google publishes a documented API access route in Play Console for accounts created after the Setup page was removed.
- Whether the 36-hour propagation and 24-hour activation windows hold for other developers or were this developer's worst case.
- Whether Apple removes further live listings for missing Digital Services Act trader details.