[{"data":1,"prerenderedAt":3579},["ShallowReactive",2],{"\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027\u002F":3,"\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027\u002F-related":616,"\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027\u002F-resources":3565},{"id":4,"title":5,"author":6,"body":10,"category":542,"createdAt":543,"description":544,"disclosure":545,"extension":546,"faq":547,"howTo":545,"lastVerified":545,"location":563,"meta":564,"navigation":346,"ogImage":545,"path":570,"primaryKeyword":571,"readingTime":572,"related":573,"seo":579,"sources":580,"stem":606,"tags":607,"takeaways":608,"updatedAt":543,"url":614,"__hash__":615},"blog\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027.md","Firebase ML Model Hosting Shutting Down: How to Migrate",{"name":7,"social":8},"Simon Dziak",{"twitter":9},"@SzymonDziak",{"type":11,"value":12,"toc":527},"minimark",[13,26,29,35,40,109,117,121,124,131,134,138,141,144,148,151,193,203,224,232,236,243,248,259,263,273,277,300,314,395,398,401,405,411,415,434,437,441,492,500,507,511,523],[14,15,16,20,21,25],"p",{},[17,18,19],"strong",{},"Firebase ML, including custom model hosting, will be shut down on June 15, 2027, and Firebase's named replacement for hosted TensorFlow Lite models is Cloud Storage for Firebase."," If your app downloads a ",[22,23,24],"code",{},".tflite"," model through the Firebase ML model downloader, you need to host the file somewhere else and change the download code before that date.",[14,27,28],{},"The facts below come from Firebase, Google for Developers and pub.dev, as shown in the sources. I checked each one on October 18, 2026. Google can change a date, so open the linked page before you plan around it.",[14,30,31,34],{},[17,32,33],{},"Disclosure:"," App369 is my studio. I build and fix Flutter and Firebase apps, and the last section mentions what I sell. Google doesn't pay me for anything on this page.",[36,37,39],"h2",{"id":38},"the-dated-timeline","The dated timeline",[41,42,43,59],"table",{},[44,45,46],"thead",{},[47,48,49,53,56],"tr",{},[50,51,52],"th",{},"Date",[50,54,55],{},"What happens",[50,57,58],{},"Source",[60,61,62,80,94],"tbody",{},[47,63,64,68,71],{},[65,66,67],"td",{},"Now",[65,69,70],{},"Projects that didn't previously use Firebase ML can no longer start using it",[65,72,73],{},[74,75,79],"a",{"href":76,"rel":77},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fml\u002Fmigrate-to-cloud-storage",[78],"nofollow","Firebase",[47,81,82,85,88],{},[65,83,84],{},"Now to June 15, 2027",[65,86,87],{},"Existing projects \"should begin migrating away\"",[65,89,90],{},[74,91,79],{"href":92,"rel":93},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fml",[78],[47,95,96,101,104],{},[65,97,98],{},[17,99,100],{},"June 15, 2027",[65,102,103],{},"Firebase ML is shut down",[65,105,106],{},[74,107,79],{"href":76,"rel":108},[78],[14,110,111,112,116],{},"I found no other dated step on these pages. For the other Firebase retirements, see my ",[74,113,115],{"href":114},"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026\u002F","Firebase deprecations table",".",[36,118,120],{"id":119},"what-stops-and-what-the-pages-leave-out","What stops, and what the pages leave out",[14,122,123],{},"Firebase's banner on its Firebase ML pages reads: \"Firebase ML is deprecated and will be shut down on June 15, 2027.\" For TensorFlow Lite models used for local inference, it says to migrate your apps to use Cloud Storage instead.",[14,125,126,127,130],{},"Here is what I could not confirm. The Android model downloader page describes ",[22,128,129],{},"getModel()"," fetching a model you deployed to Firebase, caching it on the device and updating it by download type. None of the pages I read say which of those calls fail on June 15, 2027, or what happens to an app already in the store. They also do not mention the Admin SDK or REST model management. I am leaving those out rather than guessing.",[14,132,133],{},"My advice: assume anything that talks to Firebase ML for models stops working on June 15, 2027, including the model downloader in apps you already shipped. Old app versions in users' hands are the real risk, because they keep calling the old path until people update.",[36,135,137],{"id":136},"what-about-ml-kit","What about ML Kit?",[14,139,140],{},"Firebase's migration guide does not mention ML Kit on-device APIs. The Firebase ML overview page says ML Kit's on-device APIs are available through a standalone SDK, and it does not say whether ML Kit is deprecated. The ML Kit custom models page says some ML Kit APIs let you replace the default models with custom LiteRT models, and that ML Kit only supports custom image classification models. That page does not mention Firebase ML hosting.",[14,142,143],{},"My advice: if you use ML Kit with a model you pulled through Firebase ML, check how that model gets onto the device. If it comes from Firebase ML hosting, it is covered by this guide.",[36,145,147],{"id":146},"the-migration-step-by-step","The migration, step by step",[14,149,150],{},"This is Firebase's route, which its guide splits into download, upload and configure steps. I have laid it out as seven steps, with my notes.",[152,153,154,169,175,187],"ol",{},[155,156,157,160,161,164,165,168],"li",{},[17,158,159],{},"Download your models."," In the Firebase console's Machine Learning page, open a model's three-dot menu and click Download model. For many models, click Get command for bulk download, which gives you a ",[22,162,163],{},"curl"," command. Firebase warns that these URLs expire in 7 days, and the command saves to a local ",[22,166,167],{},"hosted_models"," folder. Cloud Shell has a 5GB disk limit.",[155,170,171,174],{},[17,172,173],{},"Create a bucket."," In the console, go to Databases & Storage, then Storage. The guide says this requires a billing account. The Flutter Storage page says the project must be on the Blaze plan.",[155,176,177,180,181,183,184],{},[17,178,179],{},"Upload the files."," Upload ",[22,182,24],{}," files one at a time in the Storage section, or in bulk with Firebase's command: ",[22,185,186],{},"gcloud storage rsync --recursive .\u002Fhosted_models gs:\u002F\u002F\u003Cyour-storage-bucket>\u002Fmodels\u002F",[155,188,189,192],{},[17,190,191],{},"Set Storage security rules"," so your app can read the files. The guide says to ensure your rules allow reads, for example by restricting access to authenticated users. Firebase's rules page shows a pattern like this one, which allows reads and writes to signed-in users. For model files, allow read only, as in the sketch below (my example, not Firebase's), and keep uploads to the console or a trusted admin:",[194,195,200],"pre",{"className":196,"code":198,"language":199},[197],"language-text","service firebase.storage {\n  match \u002Fb\u002F{bucket}\u002Fo {\n    match \u002Fmodels\u002F{fileName} {\n      allow read: if request.auth != null;\n    }\n  }\n}\n","text",[22,201,198],{"__ignoreMap":202},"",[152,204,206,212,218],{"start":205},5,[155,207,208,211],{},[17,209,210],{},"Add the Storage SDK"," for your platform, using Firebase's setup guides for Android, Apple or Flutter.",[155,213,214,217],{},[17,215,216],{},"Change the app code"," to download from Storage, then load the file with your existing TensorFlow Lite library.",[155,219,220,223],{},[17,221,222],{},"Optional: Remote Config."," Firebase suggests it for updating model paths without a new app release.",[14,225,226,227,231],{},"My advice: test your security rules with a signed-out user and a signed-in user before you ship. My guide on ",[74,228,230],{"href":229},"\u002Fblog\u002Fhow-to-test-firebase-security-rules-2026\u002F","testing Firebase security rules"," shows how.",[36,233,235],{"id":234},"the-app-code-by-platform","The app code, by platform",[14,237,238,239,242],{},"Firebase's guide describes the same pattern on each platform. Get a reference to the file from its ",[22,240,241],{},"gs:\u002F\u002F"," URL, download it to a local file, then load it. I list what the guide names here, so check its page for the full samples.",[244,245,247],"h3",{"id":246},"android","Android",[14,249,250,251,254,255,258],{},"The guide gets a reference with ",[22,252,253],{},"storage.getReferenceFromUrl(\"gs:\u002F\u002FYOUR_BUCKET\u002Fpath\u002Fto\u002Fmodel.tflite\")",", creates a temp file, and calls ",[22,256,257],{},"getFile"," with success and failure listeners. After the download, you load the file into your TensorFlow Lite interpreter as before.",[244,260,262],{"id":261},"apple-platforms","Apple platforms",[14,264,250,265,268,269,272],{},[22,266,267],{},"storage.reference(forURL:)"," and downloads to a local file with ",[22,270,271],{},"write(toFile:)",", handling errors in the completion closure. Its sample uses a placeholder local path, so pick a real location in your app's container.",[244,274,276],{"id":275},"flutter","Flutter",[14,278,279,280,283,284,287,288,291,292,295,296,299],{},"The Flutter plugin you use today, ",[22,281,282],{},"firebase_ml_model_downloader",", is marked discontinued on pub.dev, with a note that Firebase ML is deprecated and will shut down on June 15, 2027. Version 0.4.5 was the latest when I checked. Replace it with ",[22,285,286],{},"firebase_storage",", which was at 14.0.0 when I checked and lists Android, iOS, macOS, Web and Windows. Add it with ",[22,289,290],{},"flutter pub add firebase_storage path_provider"," (path_provider was at 2.1.6 when I checked), run ",[22,293,294],{},"flutterfire configure"," so your default bucket name is in ",[22,297,298],{},"firebase_options.dart",", and import it.",[14,301,250,302,305,306,309,310,313],{},[22,303,304],{},"FirebaseStorage.instance.refFromURL(...)",", builds a local path under the app documents directory, calls ",[22,307,308],{},"writeToFile",", and listens to ",[22,311,312],{},"snapshotEvents"," for the task states. Here is my sketch of the same shape. It is not a copy of Firebase's sample, so test it:",[194,315,319],{"className":316,"code":317,"language":318,"meta":202,"style":202},"language-dart shiki shiki-themes github-light github-dark","import 'dart:io';\nimport 'package:firebase_storage\u002Ffirebase_storage.dart';\nimport 'package:path_provider\u002Fpath_provider.dart';\n\nFuture\u003CFile> downloadModel() async {\n  final ref = FirebaseStorage.instance\n      .refFromURL('gs:\u002F\u002FYOUR_BUCKET\u002Fmodels\u002Fmodel.tflite');\n  final dir = await getApplicationDocumentsDirectory();\n  final file = File('${dir.path}\u002Fmodel.tflite');\n  await ref.writeToFile(file);\n  return file;\n}\n","dart",[22,320,321,329,335,341,348,353,359,365,371,377,383,389],{"__ignoreMap":202},[322,323,326],"span",{"class":324,"line":325},"line",1,[322,327,328],{},"import 'dart:io';\n",[322,330,332],{"class":324,"line":331},2,[322,333,334],{},"import 'package:firebase_storage\u002Ffirebase_storage.dart';\n",[322,336,338],{"class":324,"line":337},3,[322,339,340],{},"import 'package:path_provider\u002Fpath_provider.dart';\n",[322,342,344],{"class":324,"line":343},4,[322,345,347],{"emptyLinePlaceholder":346},true,"\n",[322,349,350],{"class":324,"line":205},[322,351,352],{},"Future\u003CFile> downloadModel() async {\n",[322,354,356],{"class":324,"line":355},6,[322,357,358],{},"  final ref = FirebaseStorage.instance\n",[322,360,362],{"class":324,"line":361},7,[322,363,364],{},"      .refFromURL('gs:\u002F\u002FYOUR_BUCKET\u002Fmodels\u002Fmodel.tflite');\n",[322,366,368],{"class":324,"line":367},8,[322,369,370],{},"  final dir = await getApplicationDocumentsDirectory();\n",[322,372,374],{"class":324,"line":373},9,[322,375,376],{},"  final file = File('${dir.path}\u002Fmodel.tflite');\n",[322,378,380],{"class":324,"line":379},10,[322,381,382],{},"  await ref.writeToFile(file);\n",[322,384,386],{"class":324,"line":385},11,[322,387,388],{},"  return file;\n",[322,390,392],{"class":324,"line":391},12,[322,393,394],{},"}\n",[14,396,397],{},"One thing the model downloader did for you is caching and update logic: it kept the model on the device and updated it by download type. With Storage, you write that part. Check whether the file exists before you download it, and decide when to fetch a newer one.",[14,399,400],{},"My advice: keep a copy of the last good model on the device and only replace it after a download finishes, so a failed download never leaves you with no model.",[36,402,404],{"id":403},"bundling-the-model-instead","Bundling the model instead",[14,406,407,408,410],{},"Firebase's guide documents Cloud Storage, not bundling. I mention bundling as an option for a small model that rarely changes: you add the ",[22,409,24],{}," file as an app asset and skip the download code, the bucket and the rules. The cost is that every model change needs a new store release, and a bigger app. If your model changes often, or is large, Storage with Remote Config is the better fit.",[36,412,414],{"id":413},"optional-litert-compiledmodel","Optional: LiteRT CompiledModel",[14,416,417,418,421,422,425,426,428,429,431,432,116],{},"If your app uses the legacy TensorFlow Lite ",[22,419,420],{},"Interpreter"," API, Firebase's guide suggests moving to the LiteRT ",[22,423,424],{},"CompiledModel"," API, which it says offers improved hardware acceleration support. The LiteRT page says ",[22,427,420],{}," \"remains available for backward compatibility\" and that ",[22,430,424],{}," is where new performance and accelerator features are prioritized. It lists Kotlin, C++, Python and JavaScript examples for ",[22,433,424],{},[14,435,436],{},"I would do this as a separate change. The shutdown deadline needs the hosting move only, and mixing in an inference API change makes a bug hard to trace.",[36,438,440],{"id":439},"a-short-plan","A short plan",[152,442,443,456,462,468,474,480,486],{},[155,444,445,448,449,452,453,455],{},[17,446,447],{},"Find every use."," Search your code for ",[22,450,451],{},"firebase-ml-modeldownloader"," on Android, ",[22,454,282],{}," in Flutter and the Firebase ML model downloader on Apple platforms. Check the Machine Learning page in the console for each project.",[155,457,458,461],{},[17,459,460],{},"Download every model"," now, because the bulk URLs expire in 7 days.",[155,463,464,467],{},[17,465,466],{},"Enable billing"," and create the bucket.",[155,469,470,473],{},[17,471,472],{},"Upload, set rules and test"," with a signed-out and a signed-in user.",[155,475,476,479],{},[17,477,478],{},"Ship an app version"," that downloads from Storage, in all your platforms.",[155,481,482,485],{},[17,483,484],{},"Leave the old models in Firebase ML"," until most users have updated, then check which versions still call the old path.",[155,487,488,491],{},[17,489,490],{},"Finish well before June 15, 2027",", so a slow update cycle on the app stores doesn't strand old versions.",[14,493,494,495,499],{},"Storage downloads add to your Firebase bill. See my guide on ",[74,496,498],{"href":497},"\u002Fblog\u002Fhow-to-cut-your-firebase-bill-2026\u002F","cutting your Firebase bill"," for what to watch.",[14,501,502,503,116],{},"For every other dated Apple, Google Play and Firebase requirement in 2026 and 2027, see ",[74,504,506],{"href":505},"\u002Fblog\u002Fapp-store-google-play-deadlines-2026-2027\u002F","App Store and Google Play deadlines for 2026 and 2027",[36,508,510],{"id":509},"need-a-hand","Need a hand?",[14,512,513,514,518,519,116],{},"If your app downloads TensorFlow Lite models through Firebase ML and you want it moved before the shutdown, the ",[74,515,517],{"href":516},"\u002Ffixed-price\u002Fflutter-firebase-bug-fix\u002F","App Fix Ticket"," covers it in two fixed-price steps. A $450 Diagnosis gives you the root cause with evidence and a fixed repair quote within 3 business days, credited toward the fix. If you go ahead, the $1,200 Fix takes 5 business days and comes as a pull request. Or ",[74,520,522],{"href":521},"\u002Fcontact\u002F","send me a short description",[524,525,526],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":202,"searchDepth":331,"depth":331,"links":528},[529,530,531,532,533,538,539,540,541],{"id":38,"depth":331,"text":39},{"id":119,"depth":331,"text":120},{"id":136,"depth":331,"text":137},{"id":146,"depth":331,"text":147},{"id":234,"depth":331,"text":235,"children":534},[535,536,537],{"id":246,"depth":337,"text":247},{"id":261,"depth":337,"text":262},{"id":275,"depth":337,"text":276},{"id":403,"depth":331,"text":404},{"id":413,"depth":331,"text":414},{"id":439,"depth":331,"text":440},{"id":509,"depth":331,"text":510},"AI & Technology","2026-10-18T23:30:00.000Z","Firebase ML shuts down on June 15, 2027. What Firebase says stops, the Cloud Storage for Firebase route for TensorFlow Lite (LiteRT) models, the Android, Apple and Flutter steps, and the optional LiteRT CompiledModel move, checked October 18, 2026.",null,"md",[548,551,554,557,560],{"question":549,"answer":550},"When does Firebase ML shut down?","On June 15, 2027. Firebase's Firebase ML pages carry the banner \"Firebase ML is deprecated and will be shut down on June 15, 2027.\" Projects that didn't previously use it can no longer start using it.",{"question":552,"answer":553},"Where do I host TensorFlow Lite models instead?","Firebase points to Cloud Storage for Firebase for TensorFlow Lite models used for local inference. Its migration guide has you download each model from the Machine Learning page, upload it to a bucket, allow your app to read it in Storage security rules, and download it with the Storage SDK.",{"question":555,"answer":556},"Do I have to use Cloud Storage, or can I bundle the model in the app?","Firebase's guide documents Cloud Storage. Bundling is my own suggestion for small, stable models and is not something that guide describes. A bundled model ships with each app release, so changing it means a new build. Remote Config is the option the guide gives for changing a model path without a release.",{"question":558,"answer":559},"Does this affect ML Kit on-device APIs?","Firebase's migration pages do not mention ML Kit on-device APIs. The Firebase ML overview page says ML Kit's on-device APIs are available through a standalone SDK, but it does not state whether ML Kit itself is deprecated. The ML Kit custom models page I read does not mention Firebase ML hosting. Check the ML Kit pages for the APIs you use.",{"question":561,"answer":562},"What about Cloud Vision calls made through Firebase ML?","Firebase's notice says to migrate to Firebase AI Logic to analyze images, or to call the Cloud Vision API endpoints directly. This guide covers custom model hosting only.","Boynton Beach, FL",{"readingTimeStats":565},{"text":566,"minutes":567,"time":568,"words":569},"8 min read",7.305,438300,1461,"\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027","firebase ml model hosting shutting down","9 min",[574,575,576,577,578],"firebase-deprecations-shutdown-dates-2026","app-store-google-play-deadlines-2026-2027","firebase-extensions-shutting-down-replace-2027","how-to-test-firebase-security-rules-2026","how-to-cut-your-firebase-bill-2026",{"title":5,"description":544},[581,583,585,588,591,594,597,600,603],{"title":582,"url":76},"Firebase, migrate custom models from Firebase ML to Cloud Storage",{"title":584,"url":92},"Firebase, Firebase ML overview (deprecation banner)",{"title":586,"url":587},"Firebase, use a custom TensorFlow Lite model on Android (model downloader)","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fml\u002Fandroid\u002Fuse-custom-models",{"title":589,"url":590},"Firebase, get started with Cloud Storage on Flutter","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fstorage\u002Fflutter\u002Fstart",{"title":592,"url":593},"Firebase, Cloud Storage security rules","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fstorage\u002Fsecurity",{"title":595,"url":596},"pub.dev, firebase_ml_model_downloader","https:\u002F\u002Fpub.dev\u002Fpackages\u002Ffirebase_ml_model_downloader",{"title":598,"url":599},"pub.dev, firebase_storage","https:\u002F\u002Fpub.dev\u002Fpackages\u002Ffirebase_storage",{"title":601,"url":602},"Google AI Edge, LiteRT inference and the CompiledModel API","https:\u002F\u002Fdevelopers.google.com\u002Fedge\u002Flitert\u002Finference",{"title":604,"url":605},"Google for Developers, ML Kit custom models","https:\u002F\u002Fdevelopers.google.com\u002Fml-kit\u002Fcustom-models","blog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027","firebase ml shutting down, firebase ml model hosting, firebase ml custom model hosting deprecated, firebase_ml_model_downloader discontinued, tensorflow lite cloud storage for firebase, litert compiledmodel, firebase ml migration, flutter tflite model download, firebase deprecation 2027",[609,610,611,612,613],"Firebase ML is deprecated and will be shut down on June 15, 2027. Firebase says projects that didn't previously use it can no longer start using it, and existing projects should begin migrating away.","For TensorFlow Lite models used for local inference, Firebase's replacement is Cloud Storage for Firebase. Its guide covers downloading your models, uploading them to a bucket, and new app code for Android, Apple platforms and Flutter.","The pages I read do not say which Firebase ML calls fail first, or what happens to a shipped app after June 15, 2027. Plan on the model downloader no longer working and test your own app.","On pub.dev, the firebase_ml_model_downloader Flutter plugin (version 0.4.5 when I checked) is marked discontinued, so the Flutter move is a code change, not a version bump.","Cloud Storage for Firebase needs a Blaze plan, and the migration guide says creating the bucket requires a billing account. Budget for that before you start.","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027\u002F","HMi-T3YBMiHpJNYwo9PXVfcNm9Pr6PFXqGKRMNIve9Y",[617,1088,1800,2380],{"id":618,"title":619,"author":620,"body":622,"category":542,"createdAt":1028,"description":1029,"disclosure":545,"extension":546,"faq":1030,"howTo":545,"lastVerified":545,"location":563,"meta":1049,"navigation":346,"ogImage":545,"path":1055,"primaryKeyword":1056,"readingTime":1057,"related":1058,"seo":1061,"sources":1062,"stem":1078,"tags":1079,"takeaways":1080,"updatedAt":1028,"url":1086,"__hash__":1087},"blog\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026.md","Firebase Deprecations: Every Shutdown Date, 2024 to 2027",{"name":7,"social":621},{"twitter":9},{"type":11,"value":623,"toc":1016},[624,630,633,638,642,840,844,848,851,858,861,865,868,875,878,881,913,917,920,926,930,939,943,946,953,957,1001,1005,1007],[14,625,626,629],{},[17,627,628],{},"Firebase isn't shutting down, but seven of its products and APIs are being retired between 2024 and 2027, and five of the deadlines fall in 2027."," If your app uses Extensions, Firebase Studio, Firebase ML model hosting, Test Lab, device groups or the old FCM InstanceId APIs, you have a deadline. The table below lists each one with the date, what stops working and where Firebase says to move.",[14,631,632],{},"Every date here comes from Firebase's own documentation, linked in each row and in the sources. I checked each page on October 18, 2026. Google can change a deadline, so open the linked page before you plan around one.",[14,634,635,637],{},[17,636,33],{}," App369 is my studio. I build Flutter and Firebase apps, and I run my own product, Workspace369, on Firebase. The last section mentions what I sell. Google doesn't pay me for anything on this page.",[36,639,641],{"id":640},"every-firebase-shutdown-in-date-order","Every Firebase shutdown, in date order",[41,643,644,662],{},[44,645,646],{},[47,647,648,651,654,657,660],{},[50,649,650],{},"Deadline",[50,652,653],{},"What is retired",[50,655,656],{},"What stops working",[50,658,659],{},"Move to",[50,661,58],{},[60,663,664,697,722,744,766,786,818],{},[47,665,666,673,676,683,690],{},[65,667,668,669,672],{},"From ",[17,670,671],{},"July 22, 2024"," (done)",[65,674,675],{},"Legacy FCM HTTP and XMPP send APIs",[65,677,678,679,682],{},"Sending with a server key to ",[22,680,681],{},"fcm\u002Fsend",". Deprecated June 20, 2023",[65,684,685,686],{},"FCM HTTP v1 API or the Admin SDK. ",[74,687,689],{"href":688},"\u002Fblog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026\u002F","My guide",[65,691,692],{},[74,693,696],{"href":694,"rel":695},"https:\u002F\u002Fweb.archive.org\u002Fweb\u002F20260108211426\u002Fhttps:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fmigrate-v1",[78],"Firebase (archived)",[47,698,699,704,707,710,716],{},[65,700,701,672],{},[17,702,703],{},"August 25, 2025",[65,705,706],{},"Firebase Dynamic Links",[65,708,709],{},"Dynamic Links, and email link sign-in that relied on them",[65,711,712,713],{},"Your own deep links. For email link sign-in, Firebase Authentication Android SDK 23.2.0 or later (BoM 33.9.0 or later). ",[74,714,689],{"href":715},"\u002Fblog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026\u002F",[65,717,718],{},[74,719,79],{"href":720,"rel":721},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fauth\u002Fandroid\u002Femail-link-migration",[78],[47,723,724,729,732,735,738],{},[65,725,726],{},[17,727,728],{},"March 22, 2027",[65,730,731],{},"Firebase Studio",[65,733,734],{},"Existing workspaces. New workspaces and signups already stopped on June 22, 2026",[65,736,737],{},"Google AI Studio, Google Antigravity, or an export of your source to another platform",[65,739,740],{},[74,741,79],{"href":742,"rel":743},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fstudio\u002Fmigrating-project",[78],[47,745,746,751,754,757,760],{},[65,747,748],{},[17,749,750],{},"March 31, 2027",[65,752,753],{},"Firebase Extensions",[65,755,756],{},"Updating, reconfiguring or uninstalling extensions, or downloading their configuration, through the console or CLI. Installed extensions keep running",[65,758,759],{},"Function kits on npm where the publisher offers one, or your own Cloud Functions (2nd gen)",[65,761,762],{},[74,763,79],{"href":764,"rel":765},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions\u002Ffaq-and-troubleshooting",[78],[47,767,768,772,775,778,781],{},[65,769,770],{},[17,771,100],{},[65,773,774],{},"Firebase ML custom model hosting",[65,776,777],{},"Hosting and serving custom models through Firebase ML",[65,779,780],{},"Cloud Storage for Firebase, per Firebase's guide",[65,782,783],{},[74,784,79],{"href":76,"rel":785},[78],[47,787,788,793,796,803,812],{},[65,789,790],{},[17,791,792],{},"September 29, 2027",[65,794,795],{},"FCM InstanceId server APIs and device groups",[65,797,798,799,802],{},"Requests to ",[22,800,801],{},"iid.googleapis.com"," and device group management start failing. New users are blocked after January 1, 2027",[65,804,805,806,809,810],{},"The FCM topic subscription API, HTTP v1 with ",[22,807,808],{},"validate_only",", and sends to individual tokens. ",[74,811,689],{"href":688},[65,813,814],{},[74,815,79],{"href":816,"rel":817},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Ftroubleshooting#fcm-26-deprecation",[78],[47,819,820,825,828,831,834],{},[65,821,822],{},[17,823,824],{},"September 30, 2027",[65,826,827],{},"Firebase Test Lab",[65,829,830],{},"All of Test Lab",[65,832,833],{},"The Developer Device Platform on Google Cloud",[65,835,836],{},[74,837,79],{"href":838,"rel":839},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Ftest-lab",[78],[36,841,843],{"id":842},"what-each-2027-deadline-means-in-practice","What each 2027 deadline means in practice",[244,845,847],{"id":846},"firebase-studio-march-22-2027","Firebase Studio: March 22, 2027",[14,849,850],{},"Firebase Studio launched as a preview to explore AI-driven, full-stack app development. Firebase's migration page points to Google AI Studio, for rapid browser-based prototyping, and Google Antigravity, for code-first agentic work. You can keep working in an existing workspace until March 22, 2027. Any project you want to keep must be migrated before then, and Firebase's page has steps for both destinations and for exporting the source to anywhere else.",[14,852,853,854,116],{},"For the step-by-step move, see ",[74,855,857],{"href":856},"\u002Fblog\u002Ffirebase-studio-shutting-down-migrate-project-2027\u002F","Firebase Studio is shutting down: how to migrate",[14,859,860],{},"Your Firebase backend isn't affected. Firebase says Firestore, Authentication, App Hosting and your data keep working outside Firebase Studio. One thing to test after a move: Firebase's own FAQ has an entry about Google Sign-In not working after migrating to Google AI Studio, so check sign-in first.",[244,862,864],{"id":863},"firebase-extensions-march-31-2027","Firebase Extensions: March 31, 2027",[14,866,867],{},"This one is easy to miss, because nothing breaks on the day. Firebase says installed extensions run on standard Google Cloud services (Cloud Functions, Eventarc, Cloud Run, Cloud Tasks) and keep executing. What you lose after March 31, 2027 is control: you can't change parameters or environment variables, apply fixes or security patches, uninstall through the console or CLI, or download the configuration to set up a replacement.",[14,869,870,871,116],{},"For the inventory and function kit steps, see ",[74,872,874],{"href":873},"\u002Fblog\u002Ffirebase-extensions-shutting-down-replace-2027\u002F","Firebase Extensions are shutting down: how to replace them",[14,876,877],{},"There's a second risk. Firebase notes that most extensions are built on the legacy Cloud Functions v1 SDK and older Node.js runtimes, and that functions may stop running or be disabled when Google Cloud retires those runtimes. So an extension you can't update may stop working once those runtimes are retired, and you won't be able to patch it.",[14,879,880],{},"Before March 31, 2027:",[152,882,883,889,895,901],{},[155,884,885,888],{},[17,886,887],{},"List what's installed."," In the Firebase console, open Extensions for each project, including staging and old projects.",[155,890,891,894],{},[17,892,893],{},"Uninstall what you no longer use."," After the deadline the Uninstall button goes away, and you'd have to delete the underlying resources by hand.",[155,896,897,900],{},[17,898,899],{},"Export the configuration of the rest."," You need the parameters to set up a replacement.",[155,902,903,906,907,912],{},[17,904,905],{},"Replace each one."," Use the publisher's function kit on npm if there is one. If not, the extensions are open source, so a developer can rebuild one as Cloud Functions (2nd gen). Firebase's ",[74,908,911],{"href":909,"rel":910},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions\u002Fusers\u002Fmigrate",[78],"guide for users"," covers both.",[244,914,916],{"id":915},"firebase-ml-model-hosting-june-15-2027","Firebase ML model hosting: June 15, 2027",[14,918,919],{},"This only matters if you host custom TensorFlow Lite models through Firebase ML. On-device ML Kit features are a separate product. Firebase's suggested route is to download your models and host them in Cloud Storage for Firebase, and its guide covers Android, Apple platforms and Flutter, plus an optional move to the LiteRT CompiledModel API.",[14,921,853,922,116],{},[74,923,925],{"href":924},"\u002Fblog\u002Ffirebase-ml-model-hosting-shutting-down-migrate-2027\u002F","Firebase ML model hosting is shutting down: how to migrate",[244,927,929],{"id":928},"fcm-instanceid-apis-and-device-groups-september-29-2027","FCM InstanceId APIs and device groups: September 29, 2027",[14,931,932,933,935,936,116],{},"If your server checks tokens with ",[22,934,801],{},", manages topic subscriptions through the old InstanceId endpoints, imports APNs tokens in bulk, or uses device groups, those calls start failing after September 29, 2027. If you manage topics through an older Firebase Admin SDK, you're affected too. I cover each case and the replacement in the ",[74,937,938],{"href":688},"FCM guide",[244,940,942],{"id":941},"test-lab-september-30-2027","Test Lab: September 30, 2027",[14,944,945],{},"Test Lab runs your Android and iOS tests on devices in Google's data centers. Firebase says it will be fully shut down on September 30, 2027, and points to the Developer Device Platform on Google Cloud, with a migration guide and FAQ linked from the Test Lab page. If Test Lab runs in your CI pipeline, budget time to move it and to compare device coverage and pricing before the deadline.",[14,947,948,949,116],{},"For the options and a migration plan, see ",[74,950,952],{"href":951},"\u002Fblog\u002Ffirebase-test-lab-shutting-down-alternatives-2027\u002F","Firebase Test Lab is shutting down: alternatives for 2027",[36,954,956],{"id":955},"a-one-hour-check-for-your-project","A one-hour check for your project",[152,958,959,983,989,995],{},[155,960,961,964,965,967,968,967,971,967,974,976,977,979,980,116],{},[17,962,963],{},"Search your code"," for ",[22,966,801],{},", ",[22,969,970],{},"fcm.googleapis.com\u002Ffcm\u002F",[22,972,973],{},"page.link",[22,975,451],{}," (or ",[22,978,282],{}," in Flutter), and ",[22,981,982],{},"gcloud firebase test",[155,984,985,988],{},[17,986,987],{},"Open the Firebase console"," for every project you own and look at Extensions, Machine Learning, Test Lab and Studio.",[155,990,991,994],{},[17,992,993],{},"Write down each deadline"," that applies, with the owner of the fix and a target date at least a month early.",[155,996,997,1000],{},[17,998,999],{},"Start with the earliest deadlines."," Of the 2027 ones, Studio and Extensions come first, in March.",[14,1002,502,1003,116],{},[74,1004,506],{"href":505},[36,1006,510],{"id":509},[14,1008,1009,1010,1012,1013,1015],{},"If one of these migrations breaks something, such as pushes that stop arriving, a sign-in flow that fails after a move, or a Cloud Function that won't deploy, the ",[74,1011,517],{"href":516}," covers it in two fixed-price steps. A $450 Diagnosis gives you the root cause with evidence and a fixed repair quote within 3 business days, credited toward the fix. If you go ahead, the $1,200 Fix takes 5 business days. If you want help planning several migrations at once, ",[74,1014,522],{"href":521}," of your project.",{"title":202,"searchDepth":331,"depth":331,"links":1017},[1018,1019,1026,1027],{"id":640,"depth":331,"text":641},{"id":842,"depth":331,"text":843,"children":1020},[1021,1022,1023,1024,1025],{"id":846,"depth":337,"text":847},{"id":863,"depth":337,"text":864},{"id":915,"depth":337,"text":916},{"id":928,"depth":337,"text":929},{"id":941,"depth":337,"text":942},{"id":955,"depth":331,"text":956},{"id":509,"depth":331,"text":510},"2026-10-18T23:00:00.000Z","Every Firebase shutdown from 2024 to 2027 in one dated table: FCM legacy APIs, Dynamic Links, Firebase Studio, Extensions, Firebase ML model hosting, the FCM InstanceId APIs and Test Lab. What stops working, the deadline, and what to move to, from Firebase's own docs checked October 18, 2026.",[1031,1034,1037,1040,1043,1046],{"question":1032,"answer":1033},"Is Firebase shutting down?","No. Firebase is retiring some products and APIs, but core services such as Firestore, Authentication, Cloud Functions and Hosting are not on any shutdown list I found. Firebase says the Firebase Studio sunset doesn't affect Firestore, Authentication or App Hosting.",{"question":1035,"answer":1036},"What Firebase products are being deprecated in 2027?","Firebase Studio sunsets on March 22, 2027, Firebase Extensions shuts down on March 31, 2027, Firebase ML custom model hosting on June 15, 2027, the FCM InstanceId server APIs and device groups on September 29, 2027, and Test Lab on September 30, 2027.",{"question":1038,"answer":1039},"Will my Firebase Extensions stop working on March 31, 2027?","Not immediately. Firebase says already-deployed extensions keep running on Google Cloud infrastructure, but after March 31, 2027 you can't update, reconfigure or uninstall them through the Firebase console or CLI, or download their configuration. Firebase also warns that most extensions use the legacy Cloud Functions v1 SDK, which may stop running when older runtimes are decommissioned.",{"question":1041,"answer":1042},"What replaces Firebase Test Lab?","Firebase points Test Lab users to the Developer Device Platform on Google Cloud, with a migration guide and FAQ. Test Lab will be fully shut down on September 30, 2027.",{"question":1044,"answer":1045},"What happens to apps I built in Firebase Studio?","New workspaces and signups were disabled on June 22, 2026. You can keep working in existing workspaces until March 22, 2027, but you must migrate any project you want to keep before then. Firebase offers migration paths to Google AI Studio, Google Antigravity, or exporting the source to another platform.",{"question":1047,"answer":1048},"Where can I host custom ML models after Firebase ML?","Firebase suggests Cloud Storage for Firebase and has a guide for downloading your TensorFlow Lite models and uploading them there, with steps for Android, Apple platforms and Flutter. Firebase ML model hosting shuts down on June 15, 2027.",{"readingTimeStats":1050},{"text":1051,"minutes":1052,"time":1053,"words":1054},"6 min read",5.665,339900,1133,"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026","firebase deprecations","8 min",[1059,1060,578],"fcm-legacy-api-shutdown-http-v1-migration-2026","firebase-dynamic-links-shutdown-deep-linking-2026",{"title":619,"description":1029},[1063,1065,1067,1069,1071,1073,1074,1076],{"title":1064,"url":694},"Firebase, migrate from legacy FCM APIs to HTTP v1 (Wayback Machine copy, January 8, 2026)",{"title":1066,"url":720},"Firebase, migrating email link sign-in off Dynamic Links (Android)",{"title":1068,"url":742},"Firebase, Firebase Studio sunset and project migration",{"title":1070,"url":764},"Firebase, Firebase Extensions deprecation FAQ",{"title":1072,"url":909},"Firebase, migrate an extension to Cloud Functions as a user",{"title":582,"url":76},{"title":1075,"url":816},"Firebase, FCM InstanceId API and device group deprecation (FAQ, announced September 2026)",{"title":1077,"url":838},"Firebase, Test Lab (deprecation notice)","blog\u002Ffirebase-deprecations-shutdown-dates-2026","firebase deprecations, firebase shutdown dates, firebase extensions deprecated, firebase test lab shut down, firebase studio sunset, firebase ml model hosting shut down, firebase dynamic links shutdown, fcm legacy api shutdown, firebase deprecation 2027, firebase migration checklist",[1081,1082,1083,1084,1085],"Five Firebase deadlines fall between March and September 2027: Firebase Studio (March 22), Extensions (March 31), Firebase ML model hosting (June 15), the FCM InstanceId APIs and device groups (September 29) and Test Lab (September 30).","Two shutdowns have already happened: sending through the legacy FCM APIs, from July 22, 2024, and Firebase Dynamic Links, on August 25, 2025.","Core services such as Firestore, Authentication, Cloud Functions and Hosting are not on the list, and Firebase says the Studio sunset doesn't affect Firestore, Authentication or App Hosting.","Installed Firebase Extensions keep running after March 31, 2027, but you can no longer update, reconfigure or uninstall them through Firebase, so migrate or uninstall them before then.","Every date here comes from Firebase's own documentation, checked on October 18, 2026. Deadlines can move, so check the linked page before you plan around one.","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026\u002F","sgyFwQkpd_gLjaaP7iUNbvUv_T-ENqm8em6pY6IA67w",{"id":1089,"title":1090,"author":1091,"body":1093,"category":542,"createdAt":1728,"description":1729,"disclosure":545,"extension":546,"faq":1730,"howTo":545,"lastVerified":545,"location":563,"meta":1746,"navigation":346,"ogImage":545,"path":1751,"primaryKeyword":1752,"readingTime":1753,"related":1754,"seo":1757,"sources":1758,"stem":1789,"tags":1790,"takeaways":1791,"updatedAt":1797,"url":1798,"__hash__":1799},"blog\u002Fblog\u002Fapp-store-google-play-deadlines-2026-2027.md","App Store and Google Play Deadlines for 2026 and 2027",{"name":7,"social":1092},{"twitter":9},{"type":11,"value":1094,"toc":1720},[1095,1101,1104,1109,1113,1625,1637,1640,1652,1655,1659,1676,1679,1683,1698,1701,1705,1711,1713],[14,1096,1097,1100],{},[17,1098,1099],{},"The App Store and Google Play requirements that affect mobile app owners in 2026 and 2027 fit in one table: Xcode 26 uploads since April 28, 2026, target API 36 and Play Billing Library 8 since August 31, 2026, 16 KB page size support from February 1, 2027, and five Firebase shutdowns between March 22 and September 30, 2027."," The table below is sorted by date, and every row links to the page where the platform states it.",[14,1102,1103],{},"I checked each one on October 18, 2026. Rows whose date has passed are marked \"In effect\".",[14,1105,1106,1108],{},[17,1107,33],{}," App369 is my studio. I build and fix Android and iOS apps, mostly in Flutter, and the last section mentions what I sell. Apple and Google don't pay me for anything on this page.",[36,1110,1112],{"id":1111},"all-dates-in-order","All dates, in order",[41,1114,1115,1131],{},[44,1116,1117],{},[47,1118,1119,1121,1124,1127,1129],{},[50,1120,52],{},[50,1122,1123],{},"What changes",[50,1125,1126],{},"Status",[50,1128,58],{},[50,1130,689],{},[60,1132,1133,1160,1183,1209,1233,1255,1275,1304,1329,1356,1381,1407,1429,1453,1477,1498,1519,1540,1561,1584,1604],{},[47,1134,1135,1138,1144,1147,1154],{},[65,1136,1137],{},"January 31, 2026",[65,1139,1140,1143],{},[17,1141,1142],{},"Apple."," Apple asked developers to answer the updated age rating questions in App Store Connect by this date, to avoid an interruption when submitting app updates. Affects: every app on the App Store.",[65,1145,1146],{},"In effect",[65,1148,1149],{},[74,1150,1153],{"href":1151,"rel":1152},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Fupcoming-requirements\u002F",[78],"Apple",[65,1155,1156],{},[74,1157,1159],{"href":1158},"\u002Fblog\u002Fapp-store-age-rating-questions-update-2026\u002F","Age rating questions",[47,1161,1162,1165,1170,1172,1177],{},[65,1163,1164],{},"April 28, 2026",[65,1166,1167,1169],{},[17,1168,1142],{}," Uploads to App Store Connect must be built with Xcode 26 or later, using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26 or watchOS 26. Affects: anyone uploading a build, including Flutter apps.",[65,1171,1146],{},[65,1173,1174],{},[74,1175,1153],{"href":1151,"rel":1176},[78],[65,1178,1179],{},[74,1180,1182],{"href":1181},"\u002Fblog\u002Fitms-90725-sdk-version-issue-xcode-26-flutter-2026\u002F","ITMS-90725 and Xcode 26",[47,1184,1185,1188,1194,1196,1203],{},[65,1186,1187],{},"August 31, 2026",[65,1189,1190,1193],{},[17,1191,1192],{},"Google Play."," New apps and app updates must target Android 16 (API level 36) or higher. Wear OS and Android Automotive OS apps need API 35, and Android XR apps need API 34. Affects: anyone publishing a new app or an update.",[65,1195,1146],{},[65,1197,1198],{},[74,1199,1202],{"href":1200,"rel":1201},"https:\u002F\u002Fsupport.google.com\u002Fgoogleplay\u002Fandroid-developer\u002Fanswer\u002F11926878",[78],"Play Console Help",[65,1204,1205],{},[74,1206,1208],{"href":1207},"\u002Fblog\u002Fgoogle-play-target-api-36-android-16-requirement-2026\u002F","Target API 36",[47,1210,1211,1213,1218,1220,1227],{},[65,1212,1187],{},[65,1214,1215,1217],{},[17,1216,1192],{}," New apps and updates must use Play Billing Library 8 or later. Version 7 is no longer accepted by default. Affects: apps with in-app purchases or subscriptions.",[65,1219,1146],{},[65,1221,1222],{},[74,1223,1226],{"href":1224,"rel":1225},"https:\u002F\u002Fdeveloper.android.com\u002Fgoogle\u002Fplay\u002Fbilling\u002Fdeprecation-faq",[78],"Android Developers",[65,1228,1229],{},[74,1230,1232],{"href":1231},"\u002Fblog\u002Fplay-billing-library-7-deprecated-update-to-8-2026\u002F","Billing Library 8",[47,1234,1235,1238,1243,1245,1251],{},[65,1236,1237],{},"September 2026",[65,1239,1240,1242],{},[17,1241,1142],{}," Answers to the new social media questions in the age rating questionnaire are required when submitting new apps or updates, or apps for notarization for alternative distribution. Apple gives the month, not a day. Affects: every app on the App Store.",[65,1244,1146],{},[65,1246,1247],{},[74,1248,1153],{"href":1249,"rel":1250},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002F?id=tlur8uvi",[78],[65,1252,1253],{},[74,1254,1159],{"href":1158},[47,1256,1257,1260,1265,1267,1272],{},[65,1258,1259],{},"September 9, 2026",[65,1261,1262,1264],{},[17,1263,1142],{}," iOS and iPadOS apps uploaded to App Store Connect must target iOS 13 or later. Affects: anyone uploading an iOS or iPadOS build.",[65,1266,1146],{},[65,1268,1269],{},[74,1270,1153],{"href":1151,"rel":1271},[78],[65,1273,1274],{},"None",[47,1276,1277,1280,1285,1287,1298],{},[65,1278,1279],{},"September 14, 2026",[65,1281,1282,1284],{},[17,1283,1142],{}," Xcode 27 was released. Flutter's docs say Apple mandates the UIScene life cycle for UIKit apps built with the iOS 27 SDK, and that Flutter apps built with Xcode 27 without it fail to launch. Affects: anyone building with Xcode 27, including Flutter apps with a custom AppDelegate.",[65,1286,1146],{},[65,1288,1289,967,1294],{},[74,1290,1293],{"href":1291,"rel":1292},"https:\u002F\u002Fdocs.flutter.dev\u002Frelease\u002Fbreaking-changes\u002Fuiscenedelegate",[78],"Flutter docs",[74,1295,1153],{"href":1296,"rel":1297},"https:\u002F\u002Fdeveloper.apple.com\u002Fnews\u002Freleases\u002F",[78],[65,1299,1300],{},[74,1301,1303],{"href":1302},"\u002Fblog\u002Fflutter-uiscene-migration-xcode-27-app-wont-launch-2026\u002F","UIScene migration",[47,1305,1306,1309,1315,1317,1323],{},[65,1307,1308],{},"September 30, 2026",[65,1310,1311,1314],{},[17,1312,1313],{},"Google Play \u002F Android."," Developer verification protections begin for apps installed from participating stores in Brazil, Indonesia, Singapore and Thailand on certified devices running Android 7 or higher. Affects: anyone distributing Android apps.",[65,1316,1146],{},[65,1318,1319],{},[74,1320,1226],{"href":1321,"rel":1322},"https:\u002F\u002Fdeveloper.android.com\u002Fdeveloper-verification",[78],[65,1324,1325],{},[74,1326,1328],{"href":1327},"\u002Fblog\u002Fandroid-developer-verification-requirement-2026\u002F","Developer verification",[47,1330,1331,1334,1340,1343,1350],{},[65,1332,1333],{},"October 30, 2026",[65,1335,1336,1339],{},[17,1337,1338],{},"Google APIs."," Google says the legacy Fitbit Web API will be turned off and will no longer function or sync data. Support already ended on September 30, 2026. Affects: apps that read Fitbit data through the Fitbit Web API.",[65,1341,1342],{},"Upcoming",[65,1344,1345],{},[74,1346,1349],{"href":1347,"rel":1348},"https:\u002F\u002Fdevelopers.google.com\u002Fhealth",[78],"Google Health API",[65,1351,1352],{},[74,1353,1355],{"href":1354},"\u002Fblog\u002Fgoogle-fit-api-deprecated-health-connect-2026\u002F","Google Fit to Health Connect",[47,1357,1358,1360,1366,1368,1375],{},[65,1359,1333],{},[65,1361,1362,1365],{},[17,1363,1364],{},"Supabase."," New tables in the public schema stop getting automatic Data API access in existing projects, so they need an explicit grant. Affects: apps with a Supabase backend.",[65,1367,1342],{},[65,1369,1370],{},[74,1371,1374],{"href":1372,"rel":1373},"https:\u002F\u002Fsupabase.com\u002Fchangelog\u002F45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically",[78],"Supabase",[65,1376,1377],{},[74,1378,1380],{"href":1379},"\u002Fblog\u002Fsupabase-permission-denied-new-tables-october-30-2026\u002F","Supabase permission denied",[47,1382,1383,1386,1391,1393,1401],{},[65,1384,1385],{},"November 1, 2026",[65,1387,1388,1390],{},[17,1389,1192],{}," End of the extension Google offers for the target API 36 and Billing Library 7 deadlines. Affects: anyone who requested an extension.",[65,1392,1342],{},[65,1394,1395,967,1398],{},[74,1396,1202],{"href":1200,"rel":1397},[78],[74,1399,1226],{"href":1224,"rel":1400},[78],[65,1402,1403,967,1405],{},[74,1404,1208],{"href":1207},[74,1406,1232],{"href":1231},[47,1408,1409,1412,1417,1419,1425],{},[65,1410,1411],{},"End of 2026",[65,1413,1414,1416],{},[17,1415,1338],{}," The Google Fit APIs, including the REST API, are supported only until the end of 2026. Affects: apps that read fitness data through Google Fit.",[65,1418,1342],{},[65,1420,1421],{},[74,1422,1226],{"href":1423,"rel":1424},"https:\u002F\u002Fdeveloper.android.com\u002Fhealth-and-fitness\u002Fhealth-connect\u002Fmigration\u002Ffit",[78],[65,1426,1427],{},[74,1428,1355],{"href":1354},[47,1430,1431,1434,1440,1442,1448],{},[65,1432,1433],{},"January 1, 2027",[65,1435,1436,1439],{},[17,1437,1438],{},"Firebase."," New users can no longer start using the FCM InstanceId server APIs and device groups. Firebase says new users can onboard before this date. Affects: new integrations that use those APIs.",[65,1441,1342],{},[65,1443,1444],{},[74,1445,79],{"href":1446,"rel":1447},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Ftroubleshooting",[78],[65,1449,1450],{},[74,1451,1452],{"href":688},"FCM migration",[47,1454,1455,1458,1463,1465,1471],{},[65,1456,1457],{},"February 1, 2027",[65,1459,1460,1462],{},[17,1461,1192],{}," Updates that don't support 16 KB memory page sizes can't be released, for apps targeting Android 15 (API level 35) and higher. Affects: apps with native code, which includes Flutter apps.",[65,1464,1342],{},[65,1466,1467],{},[74,1468,1226],{"href":1469,"rel":1470},"https:\u002F\u002Fdeveloper.android.com\u002Fguide\u002Fpractices\u002Fpage-sizes",[78],[65,1472,1473],{},[74,1474,1476],{"href":1475},"\u002Fblog\u002Fgoogle-play-16kb-page-size-flutter-android-2026\u002F","16 KB page size",[47,1478,1479,1482,1487,1489,1494],{},[65,1480,1481],{},"2027 (no month stated)",[65,1483,1484,1486],{},[17,1485,1313],{}," Developer verification capability expands globally for all apps on certified Android devices. Affects: anyone distributing Android apps.",[65,1488,1342],{},[65,1490,1491],{},[74,1492,1226],{"href":1321,"rel":1493},[78],[65,1495,1496],{},[74,1497,1328],{"href":1327},[47,1499,1500,1502,1507,1509,1514],{},[65,1501,728],{},[65,1503,1504,1506],{},[17,1505,1438],{}," Firebase Studio shuts down and remaining data is permanently deleted. Affects: anyone with a Firebase Studio workspace.",[65,1508,1342],{},[65,1510,1511],{},[74,1512,79],{"href":742,"rel":1513},[78],[65,1515,1516],{},[74,1517,1518],{"href":856},"Firebase Studio shutdown",[47,1520,1521,1523,1528,1530,1535],{},[65,1522,750],{},[65,1524,1525,1527],{},[17,1526,1438],{}," Firebase Extensions service shuts down. Installed extensions keep running, but you lose the ability to update, reconfigure or uninstall them through the console or CLI. Affects: apps with installed extensions.",[65,1529,1342],{},[65,1531,1532],{},[74,1533,79],{"href":764,"rel":1534},[78],[65,1536,1537],{},[74,1538,1539],{"href":873},"Firebase Extensions shutdown",[47,1541,1542,1544,1549,1551,1556],{},[65,1543,100],{},[65,1545,1546,1548],{},[17,1547,1438],{}," Firebase ML custom model hosting shuts down. Affects: apps that host custom models in Firebase ML.",[65,1550,1342],{},[65,1552,1553],{},[74,1554,79],{"href":76,"rel":1555},[78],[65,1557,1558],{},[74,1559,1560],{"href":924},"Firebase ML model hosting shutdown",[47,1562,1563,1566,1571,1573,1578],{},[65,1564,1565],{},"August 31, 2027",[65,1567,1568,1570],{},[17,1569,1192],{}," Billing Library 8 reaches its own deadline. New apps and updates must use Billing Library 9 or later. Extension available until November 1, 2027. Affects: apps with in-app purchases or subscriptions.",[65,1572,1342],{},[65,1574,1575],{},[74,1576,1226],{"href":1224,"rel":1577},[78],[65,1579,1580],{},[74,1581,1583],{"href":1582},"\u002Fblog\u002Fplay-billing-library-9-migration-deadline-2027\u002F","Billing Library 9",[47,1585,1586,1588,1593,1595,1600],{},[65,1587,792],{},[65,1589,1590,1592],{},[17,1591,1438],{}," The FCM InstanceId server APIs and device groups are decommissioned. Affects: servers that manage topics or tokens through the old APIs.",[65,1594,1342],{},[65,1596,1597],{},[74,1598,79],{"href":1446,"rel":1599},[78],[65,1601,1602],{},[74,1603,1452],{"href":688},[47,1605,1606,1608,1613,1615,1620],{},[65,1607,824],{},[65,1609,1610,1612],{},[17,1611,1438],{}," Firebase Test Lab is fully shut down. Affects: CI pipelines that run tests on Test Lab.",[65,1614,1342],{},[65,1616,1617],{},[74,1618,79],{"href":838,"rel":1619},[78],[65,1621,1622],{},[74,1623,1624],{"href":951},"Firebase Test Lab shutdown",[14,1626,1627,1628,1632,1633,1636],{},"Two more notes. Apple's privacy manifest rules (May 1, 2024 for required reason APIs and February 12, 2025 for common SDKs, see the ",[74,1629,1631],{"href":1630},"\u002Fblog\u002Fapple-privacy-manifest-itms-91053-itms-91061-flutter-fix-2026\u002F","privacy manifest guide",") and the FCM legacy send shutdown (July 22, 2024, see the ",[74,1634,1635],{"href":688},"FCM migration guide",") already passed before 2026. I keep them in their own guides because they still cause upload and delivery errors.",[36,1638,1153],{"id":1639},"apple",[14,1641,1642,1643,967,1645,1648,1649,116],{},"Apple's page names one build rule that matters most: Xcode 26 or later since April 28, 2026. As of October 18, 2026, it lists no Xcode 27 upload requirement. The bigger change with Xcode 27 is the UIScene life cycle, which a Flutter app on 3.41 or later with an unmodified AppDelegate gets automatically. A custom AppDelegate needs manual changes. The guides are ",[74,1644,1182],{"href":1181},[74,1646,1647],{"href":1302},"UIScene and Xcode 27"," and ",[74,1650,1651],{"href":1630},"privacy manifest errors",[14,1653,1654],{},"My advice: check which Xcode your build machine uses before your next upload, and test a build with Xcode 27 before you need one.",[36,1656,1658],{"id":1657},"google-play-and-android","Google Play and Android",[14,1660,1661,1662,1665,1666,967,1669,967,1671,1648,1673,116],{},"The Play rules come in pairs. Target API 36 and Billing Library 8 both took effect on August 31, 2026 with an extension to November 1, 2026. After that, February 1, 2027 brings the 16 KB page size rule, and on August 31, 2027 Google requires Billing Library 9 or later for new apps and updates. The ",[74,1663,1664],{"href":1582},"Billing Library 9 guide"," covers that move. Separately, Android developer verification started on September 30, 2026 in four countries, with a global expansion in 2027. The guides are ",[74,1667,1668],{"href":1207},"target API 36",[74,1670,1476],{"href":1475},[74,1672,1232],{"href":1231},[74,1674,1675],{"href":1327},"developer verification",[14,1677,1678],{},"My advice: if you are still behind on API 36 or Billing 8, ship that update before November 1, 2026. Then do the 16 KB check before February 1, 2027, since it is the next date that can block a release.",[36,1680,1682],{"id":1681},"firebase-and-google-apis","Firebase and Google APIs",[14,1684,1685,1686,967,1689,967,1692,1694,1695,116],{},"Firebase has five shutdown dates in 2027, plus the January 1 cutoff for new users of the InstanceId APIs. Firestore, Authentication, Cloud Functions and Hosting are not on the list. Google Fit APIs are supported only until the end of 2026, and Google points to Health Connect and the Google Health API. The legacy Fitbit Web API goes first: Google says it will be turned off on October 30, 2026. The guides are ",[74,1687,1688],{"href":114},"Firebase shutdown dates",[74,1690,1691],{"href":688},"FCM HTTP v1 migration",[74,1693,1355],{"href":1354}," and, if you use it, ",[74,1696,1697],{"href":1379},"Supabase new table permissions",[14,1699,1700],{},"My advice: open the Firebase console for every project you own and look at Extensions, Machine Learning, Test Lab and Studio. Those are the products with a date attached.",[36,1702,1704],{"id":1703},"how-i-keep-this-page-current","How I keep this page current",[14,1706,1707,1708,116],{},"Every row links to the page where the platform states the date. If a source says only a month or \"later this year\", I write exactly that. When a platform moves a date, I change the row and the updated date at the top of this page. If you spot a date that looks wrong, ",[74,1709,1710],{"href":521},"tell me",[36,1712,510],{"id":509},[14,1714,1715,1716,518,1718,116],{},"If one of these deadlines lands on an app you can't update yourself, the ",[74,1717,517],{"href":516},[74,1719,522],{"href":521},{"title":202,"searchDepth":331,"depth":331,"links":1721},[1722,1723,1724,1725,1726,1727],{"id":1111,"depth":331,"text":1112},{"id":1639,"depth":331,"text":1153},{"id":1657,"depth":331,"text":1658},{"id":1681,"depth":331,"text":1682},{"id":1703,"depth":331,"text":1704},{"id":509,"depth":331,"text":510},"2026-10-18T22:00:00.000Z","One dated table of the App Store, Google Play, Firebase and Google API requirements that affect mobile app owners in 2026 and 2027, with the primary source for each date, checked October 18, 2026.",[1731,1734,1737,1740,1743],{"question":1732,"answer":1733},"What is the next Google Play deadline?","The deadline of November 1, 2026 is the end of the extension window for the target API 36 and Billing Library 7 deadlines. After that, the next one is February 1, 2027, when Google says app updates that don't support 16 KB memory page sizes can't be released.",{"question":1735,"answer":1736},"What Xcode version does the App Store require?","Apple's upcoming requirements page says that since April 28, 2026, apps uploaded to App Store Connect must be built with Xcode 26 or later using an SDK for iOS 26, iPadOS 26, tvOS 26, visionOS 26 or watchOS 26. As of October 18, 2026, the page lists no Xcode 27 requirement.",{"question":1738,"answer":1739},"Do these deadlines apply to apps already published?","It depends on the rule. Google says existing apps must target API 35 or higher to stay available to new users on newer Android versions, and existing apps keep working on version 7 of Play Billing until you ship an update. Most upload-side rules, such as the Xcode SDK minimum, apply when you submit a new build.",{"question":1741,"answer":1742},"Which deadlines affect a Flutter app?","Nearly all of the Apple and Google Play rows do, because a Flutter app is a normal iOS and Android app underneath. The Firebase rows apply only if you use that Firebase product. The Supabase row applies only if you use Supabase.",{"question":1744,"answer":1745},"How will I know if a date changes?","Each row links to the page where the platform states the date, and I list the date I checked it. Dates can move, so check the linked page before you plan around one. I update this page when a platform changes a date.",{"readingTimeStats":1747},{"text":566,"minutes":1748,"time":1749,"words":1750},7.03,421800,1406,"\u002Fblog\u002Fapp-store-google-play-deadlines-2026-2027","app store deadlines 2026","6 min",[1755,1756,574],"google-play-target-api-36-android-16-requirement-2026","itms-90725-sdk-version-issue-xcode-26-flutter-2026",{"title":1090,"description":1729},[1759,1761,1763,1765,1767,1769,1771,1773,1775,1777,1779,1781,1783,1785,1787],{"title":1760,"url":1347},"Google for Developers, Google Health API (Fitbit Web API dates)",{"title":1762,"url":1151},"Apple Developer, Upcoming requirements",{"title":1764,"url":1296},"Apple Developer, Releases",{"title":1766,"url":1291},"Flutter docs, Migrate to UIScene life cycle",{"title":1768,"url":1200},"Play Console Help, Target API level requirements for Google Play apps",{"title":1770,"url":1224},"Android Developers, Play Billing Library deprecation FAQ",{"title":1772,"url":1469},"Android Developers, Support 16 KB page sizes",{"title":1774,"url":1321},"Android Developers, Android developer verification",{"title":1776,"url":1423},"Android Developers, Migrate from the Google Fit APIs",{"title":1778,"url":1446},"Firebase, FCM troubleshooting (InstanceId and device groups deprecation)",{"title":1780,"url":742},"Firebase, Migrate from Firebase Studio",{"title":1782,"url":764},"Firebase, Extensions FAQ and troubleshooting",{"title":1784,"url":76},"Firebase, Migrate Firebase ML model hosting to Cloud Storage",{"title":1786,"url":838},"Firebase, Test Lab",{"title":1788,"url":1372},"Supabase changelog, Tables not exposed to the Data API automatically","blog\u002Fapp-store-google-play-deadlines-2026-2027","app store deadlines 2026, google play deadlines 2026, app store requirements 2027, google play requirements 2027, target api 36 deadline, play billing library 8 deadline, 16 kb page size deadline, xcode 26 requirement, firebase shutdown dates, mobile app compliance calendar",[1792,1793,1794,1795,1796],"Most 2026 deadlines have already hit. Since April 28, 2026 iOS uploads need Xcode 26 or later, and since August 31, 2026 Google Play needs new apps and updates to target API 36 and use Play Billing Library 8.","Google lets you request an extension for both Play deadlines until November 1, 2026. That is the last date to ship an update if you are still behind.","The next hard date for Android is February 1, 2027. Google says updates that don't support 16 KB memory page sizes can't be released after that.","On iOS, apps built with Xcode 27 must use the UIScene life cycle or they fail to launch. Xcode 27 was released on September 14, 2026.","Firebase has five shutdowns between March 22 and September 30, 2027. Core services such as Firestore and Authentication are not on the list.","2026-10-19T04:20:00.000Z","https:\u002F\u002Fapp369.com\u002Fblog\u002Fapp-store-google-play-deadlines-2026-2027\u002F","19lvx5VBPquv9SPL4eiS0kC0-3W1OaVa3c35l8ESEl0",{"id":1801,"title":1802,"author":1803,"body":1805,"category":542,"createdAt":2316,"description":2317,"disclosure":545,"extension":546,"faq":2318,"howTo":545,"lastVerified":545,"location":563,"meta":2334,"navigation":346,"ogImage":545,"path":2339,"primaryKeyword":2340,"readingTime":1057,"related":2341,"seo":2343,"sources":2344,"stem":2370,"tags":2371,"takeaways":2372,"updatedAt":2316,"url":2378,"__hash__":2379},"blog\u002Fblog\u002Ffirebase-extensions-shutting-down-replace-2027.md","Firebase Extensions Shutting Down: Replace Them by 2027",{"name":7,"social":1804},{"twitter":9},{"type":11,"value":1806,"toc":2299},[1807,1813,1816,1820,1822,1879,1884,1888,1891,1894,1906,1909,1912,1916,1919,1922,1925,1929,1932,1938,1941,1947,1967,1971,1974,1978,1981,2020,2023,2027,2034,2040,2058,2075,2084,2088,2095,2099,2110,2114,2140,2195,2198,2204,2211,2233,2237,2252,2256,2283,2286,2290,2292],[14,1808,1809,1812],{},[17,1810,1811],{},"The Firebase Extensions service shuts down on March 31, 2027, and Firebase says extensions you already installed keep running but can no longer be updated, reconfigured or uninstalled through the console or CLI."," Firebase's recommended replacement is a self-managed function kit, which is regular Cloud Functions code that lives in your own repository.",[14,1814,1815],{},"The facts below come from Firebase's documentation and a few GitHub repositories, as shown in the sources. I checked each one on October 18, 2026. Google can change a date, so open the linked page before you plan around it.",[14,1817,1818,34],{},[17,1819,33],{},[36,1821,39],{"id":38},[41,1823,1824,1834],{},[44,1825,1826],{},[47,1827,1828,1830,1832],{},[50,1829,52],{},[50,1831,55],{},[50,1833,58],{},[60,1835,1836,1851,1864],{},[47,1837,1838,1841,1844],{},[65,1839,1840],{},"June 18, 2026",[65,1842,1843],{},"The Stripe-built Firebase extensions repository is archived by its owner and marked not actively maintained",[65,1845,1846],{},[74,1847,1850],{"href":1848,"rel":1849},"https:\u002F\u002Fgithub.com\u002Finvertase\u002Fstripe-firebase-extensions",[78],"GitHub",[47,1852,1853,1855,1858],{},[65,1854,1237],{},[65,1856,1857],{},"Per the FAQ, additional migration guidance and tools are due this month, and two migration paths are officially supported from it. The page keeps the future tense. The migration guide and the BigQuery kit on npm are live now",[65,1859,1860],{},[74,1861,1863],{"href":764,"rel":1862},[78],"Firebase FAQ",[47,1865,1866,1870,1873],{},[65,1867,1868],{},[17,1869,750],{},[65,1871,1872],{},"The Firebase Extensions service shuts down. Installed extensions keep executing, but key management features are no longer available",[65,1874,1875],{},[74,1876,79],{"href":1877,"rel":1878},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions",[78],[14,1880,1881,1882,116],{},"For the other Firebase retirements, see my ",[74,1883,115],{"href":114},[36,1885,1887],{"id":1886},"what-firebase-says-happens-to-installed-extensions","What Firebase says happens to installed extensions",[14,1889,1890],{},"The notice on the Extensions page reads: \"The Firebase Extensions service is deprecated and will shut down on March 31, 2027.\" It says already installed extensions will execute indefinitely, and recommends moving to self-managed function kits.",[14,1892,1893],{},"The FAQ spells out the loss. Deployed extensions run on standard Google Cloud infrastructure. After March 31, 2027, you cannot update, reconfigure or uninstall them through the console or CLI, and you cannot download their existing configuration. In practice, Firebase says that means you cannot:",[1895,1896,1897,1900,1903],"ul",{},[155,1898,1899],{},"change parameters or environment variables",[155,1901,1902],{},"apply bug fixes, security patches or dependency upgrades",[155,1904,1905],{},"download the configuration to recreate the setup elsewhere",[14,1907,1908],{},"There is a second risk. Firebase says most extensions use the legacy Cloud Functions v1 SDK. Once Google decommissions the older Node.js runtimes, those functions may stop running or be disabled. After that, the console's Uninstall button and the related CLI commands are removed, and you would have to delete the resources by hand in the Google Cloud console.",[14,1910,1911],{},"My advice: treat March 31, 2027 as the last day you can still change anything, not as the day things break. Plan the move for the winter, while the tools still work.",[36,1913,1915],{"id":1914},"what-an-extension-leaves-in-your-project","What an extension leaves in your project",[14,1917,1918],{},"Firebase's FAQ says that after the shutdown you would delete these by hand in the Google Cloud console: the individual Cloud Functions, Secret Manager secrets, Cloud Tasks queues and custom IAM service accounts.",[14,1920,1921],{},"The FAQ also says extensions run on Cloud Functions, Eventarc, Cloud Run and Cloud Tasks, and that the Stream Firestore to BigQuery extension creates BigQuery datasets, tables and views during setup.",[14,1923,1924],{},"Those four kinds of resource matter because they are what you would delete manually once the uninstall button is gone. The best-practices page also describes what installing and deploying a kit creates: functions, Eventarc triggers, Cloud Tasks queues and a service account with IAM roles. It does not say what remains after an uninstall, so check your project's resources after you remove one.",[36,1926,1928],{"id":1927},"step-1-list-what-you-have-installed","Step 1: list what you have installed",[14,1930,1931],{},"Firebase's user migration guide gives this command:",[194,1933,1936],{"className":1934,"code":1935,"language":199},[197],"firebase ext:list --project my-project\n",[22,1937,1935],{"__ignoreMap":202},[14,1939,1940],{},"Firebase says the output shows Extension, Publisher, Instance ID, State, Version, Your last update and Replacement Kit. The console Extensions page also shows replacement availability. The CLI output carries a notice that Firebase Extensions will shut down on March 31, 2027.",[14,1942,1943,1944,116],{},"Run it for every project you own, including staging and old ones. For instance IDs only, the best-practices page gives ",[22,1945,1946],{},"firebase ext:list --json --project \u003Cproject-id> | jq -r '.result[].instanceId'",[14,1948,1949,1950,1953,1954,967,1957,967,1960,967,1963,1966],{},"The guide needs ",[22,1951,1952],{},"firebase-tools"," 15.32.0 or later. Firebase also lists the IAM roles you need, including ",[22,1955,1956],{},"roles\u002Ffirebaseextensions.editor",[22,1958,1959],{},"roles\u002Fcloudbuild.builds.editor",[22,1961,1962],{},"roles\u002Fartifactregistry.writer",[22,1964,1965],{},"roles\u002Frun.developer"," and the two service account roles. If a role is missing, the migration fails, so check before you start.",[36,1968,1970],{"id":1969},"step-2-uninstall-what-you-dont-use","Step 2: uninstall what you don't use",[14,1972,1973],{},"Firebase says users who no longer need an extension should uninstall it before March 31, 2027. This is the cheapest fix. Every extension you remove is one less thing to migrate.",[36,1975,1977],{"id":1976},"step-3-pick-one-of-firebases-two-paths","Step 3: pick one of Firebase's two paths",[14,1979,1980],{},"Firebase says it officially supports two primary pathways.",[41,1982,1983,1996],{},[44,1984,1985],{},[47,1986,1987,1990,1993],{},[50,1988,1989],{},"Path",[50,1991,1992],{},"Firebase recommends it for",[50,1994,1995],{},"What you do",[60,1997,1998,2009],{},[47,1999,2000,2003,2006],{},[65,2001,2002],{},"NPM-shared function kit",[65,2004,2005],{},"Stream Firestore to BigQuery and other kits published on npm",[65,2007,2008],{},"Install a kit built on the Cloud Functions v2 SDK through the CLI",[47,2010,2011,2014,2017],{},[65,2012,2013],{},"Fork and self-manage",[65,2015,2016],{},"Extensions with no npm kit",[65,2018,2019],{},"Fork the source, refactor the triggers into v2 functions, and maintain the code yourself",[14,2021,2022],{},"Firebase also says upgrading to v2 is strongly recommended, and required for function kits.",[244,2024,2026],{"id":2025},"the-kit-path-in-firebases-words","The kit path, in Firebase's words",[14,2028,2029,2030,2033],{},"The user guide calls ",[22,2031,2032],{},"ext:migrate"," the recommended option:",[194,2035,2038],{"className":2036,"code":2037,"language":199},[197],"firebase ext:migrate --project \u003Cproject-id>\n",[22,2039,2037],{"__ignoreMap":202},[14,2041,2042,2043,2046,2047,2050,2051,2054,2055,2057],{},"You can narrow it with ",[22,2044,2045],{},"--extension firebase\u002Ffirestore-bigquery-export"," or ",[22,2048,2049],{},"--ext-instance \u003Cinstance-id>",". Firebase describes the command as one that selects the extension and instance, updates it, installs and configures the kit, deploys it, verifies it and uninstalls the extension. It warns that ",[22,2052,2053],{},"--force"," deletes the extension right after deploying the kit, with no verification. I would not use ",[22,2056,2053],{}," on a production project.",[14,2059,2060,2061,1648,2064,2067,2068,2071,2072,116],{},"The manual option is two steps. First update the extension with ",[22,2062,2063],{},"firebase ext:update \u003Cextension-instance-id> --project \u003Cproject-id>",[22,2065,2066],{},"firebase deploy --only extensions --project \u003Cproject-id>",". Then install the kit with ",[22,2069,2070],{},"firebase functions:kits:install --template migration --no-configure --package \u003Cnpm-package-name> --project \u003Cproject-id>",". That creates a directory under ",[22,2073,2074],{},"function-kits\u002F",[14,2076,2077,2078,1648,2081,116],{},"Firebase says kits are standard 2nd gen Cloud Functions managed with the Firebase CLI. Event-triggered kits use Eventarc, which can take a few minutes to provision. To check a kit after deploy, the guide lists ",[22,2079,2080],{},"firebase functions:logs",[22,2082,2083],{},"firebase functions:list | grep kit-\u003Ckit instance id>",[244,2085,2087],{"id":2086},"save-your-configuration-first","Save your configuration first",[14,2089,2090,2091,2094],{},"Firebase says that if you cannot migrate in time, save the configuration now, because after March 31, 2027 you cannot fetch it. The best-practices page uses ",[22,2092,2093],{},"firebase ext:export --mode functions",". Open the page's \"Saving configuration for future migration\" section for the exact syntax and output files.",[244,2096,2098],{"id":2097},"undoing-a-migration","Undoing a migration",[14,2100,2101,2102,2105,2106,2109],{},"Firebase's warning here is specific. To undo, reinstall the extension first, then run ",[22,2103,2104],{},"firebase functions:kits:uninstall --instance \u003Ckit-instance-id> --project \u003Cproject-id>",". The page says not to uninstall the kit before reinstalling the extension, or the CLI will delete the ",[22,2107,2108],{},".env"," file.",[36,2111,2113],{"id":2112},"which-popular-extensions-have-a-documented-kit","Which popular extensions have a documented kit",[14,2115,2116,2117,2120,2121,967,2124,967,2127,967,2130,967,2133,1648,2136,2139],{},"The firebase\u002Fextensions repository has a ",[22,2118,2119],{},"kits"," branch with 13 kit folders, including ",[22,2122,2123],{},"firestore-bigquery-export",[22,2125,2126],{},"firestore-send-email",[22,2128,2129],{},"storage-resize-images",[22,2131,2132],{},"firestore-counter",[22,2134,2135],{},"firestore-translate-text",[22,2137,2138],{},"delete-user-data",". The main repository page itself carries no shutdown notice and says nothing about replacements, so the facts below come from each kit's README.",[41,2141,2142,2155],{},[44,2143,2144],{},[47,2145,2146,2149,2152],{},[50,2147,2148],{},"Extension",[50,2150,2151],{},"Kit package",[50,2153,2154],{},"What its README says",[60,2156,2157,2170,2183],{},[47,2158,2159,2162,2167],{},[65,2160,2161],{},"Stream Firestore to BigQuery",[65,2163,2164],{},[22,2165,2166],{},"@firebase-function-kits\u002Ffirestore-bigquery-export",[65,2168,2169],{},"Has a \"Migrating from the extension\" section. Released on npm (0.1.1 on October 18, 2026)",[47,2171,2172,2175,2180],{},[65,2173,2174],{},"Trigger Email from Firestore",[65,2176,2177],{},[22,2178,2179],{},"@firebase-function-kits\u002Ffirestore-send-email",[65,2181,2182],{},"Has a section on differences from the extension. Carries a pre-release notice",[47,2184,2185,2188,2193],{},[65,2186,2187],{},"Resize Images",[65,2189,2190],{},[22,2191,2192],{},"@firebase-function-kits\u002Fstorage-resize-images",[65,2194,2182],{},[14,2196,2197],{},"The BigQuery kit README gives this migration command, run from your Firebase project directory:",[194,2199,2202],{"className":2200,"code":2201,"language":199},[197],"firebase ext:migrate --ext-instance \u003Cinstance-id>\n",[22,2203,2201],{"__ignoreMap":202},[14,2205,2206,2207,2210],{},"It says the command exports the instance's configuration, deploys the kit, then offers to uninstall the extension. It also warns that writes made while the new trigger warms up can reach neither exporter. To avoid that gap, the README says to answer no to the uninstall prompt, confirm the kit logs every write, then run ",[22,2208,2209],{},"firebase ext:uninstall \u003Cinstance-id> --immediate",". It says running both at once is safe, because BigQuery deduplicates on the shared event ID on a best-effort basis.",[14,2212,2213,2214,2217,2218,2221,2222,2225,2226,2229,2230,2232],{},"For the email and image kits, the READMEs I read say the kit \"has not been released yet,\" that the npm ",[22,2215,2216],{},"latest"," tag is a placeholder, and that pre-release builds are published under the ",[22,2219,2220],{},"next"," tag. Both mention ",[22,2223,2224],{},"firebase ext:migrate",", which prompts for a region and writes ",[22,2227,2228],{},"FUNCTION_DEFAULT_REGION"," to your ",[22,2231,2108],{},". Check the README and the npm page for release status before you plan a production move to either one.",[244,2234,2236],{"id":2235},"the-stripe-payments-extension","The Stripe payments extension",[14,2238,2239,2240,2243,2244,2247,2248,2251],{},"This one has a different history. Stripe's repository, described as \"Repository of Firebase Extensions built by Stripe,\" was archived by its owner on June 18, 2026. Its notice says the repository is not actively maintained and that no further updates, bug fixes or support will be provided. It also records a 2023 notice that the payments extension was transferred to Invertase, with a recommendation to uninstall ",[22,2241,2242],{},"stripe\u002Ffirestore-stripe-payments"," and install ",[22,2245,2246],{},"invertase\u002Ffirestore-stripe-payments",". The page says nothing about the Firebase Extensions shutdown. So if you run a Stripe extension, check which publisher your instance comes from in the ",[22,2249,2250],{},"ext:list"," output.",[36,2253,2255],{"id":2254},"a-short-checklist","A short checklist",[152,2257,2258,2265,2268,2271,2274,2277,2280],{},[155,2259,2260,2261,2264],{},"Run ",[22,2262,2263],{},"firebase ext:list"," in every project and write down each instance.",[155,2266,2267],{},"Save the configuration of every extension, because you can't fetch it after March 31, 2027.",[155,2269,2270],{},"Uninstall every extension you no longer use, once its config is saved.",[155,2272,2273],{},"For each one, check the Replacement Kit column and the kit's README.",[155,2275,2276],{},"If there is no kit, plan a fork or a rewrite as Cloud Functions v2.",[155,2278,2279],{},"Run the replacement before you uninstall the old one. Only the BigQuery kit README says both can run at once. For email or image extensions, test in a staging project or pause writers so you don't send or process twice.",[155,2281,2282],{},"Finish well before March 31, 2027.",[14,2284,2285],{},"My advice: migrate the extension that touches money or user data first, and keep the old one installed until the replacement has logged real traffic. For email or image extensions, do that check in a staging project first, so nothing is sent or processed twice.",[14,2287,502,2288,116],{},[74,2289,506],{"href":505},[36,2291,510],{"id":509},[14,2293,2294,2295,518,2297,116],{},"If your app depends on Firebase Extensions and you want them replaced with code you control before the shutdown, the ",[74,2296,517],{"href":516},[74,2298,522],{"href":521},{"title":202,"searchDepth":331,"depth":331,"links":2300},[2301,2302,2303,2304,2305,2306,2311,2314,2315],{"id":38,"depth":331,"text":39},{"id":1886,"depth":331,"text":1887},{"id":1914,"depth":331,"text":1915},{"id":1927,"depth":331,"text":1928},{"id":1969,"depth":331,"text":1970},{"id":1976,"depth":331,"text":1977,"children":2307},[2308,2309,2310],{"id":2025,"depth":337,"text":2026},{"id":2086,"depth":337,"text":2087},{"id":2097,"depth":337,"text":2098},{"id":2112,"depth":331,"text":2113,"children":2312},[2313],{"id":2235,"depth":337,"text":2236},{"id":2254,"depth":331,"text":2255},{"id":509,"depth":331,"text":510},"2026-10-19T00:15:00.000Z","Firebase Extensions shuts down on March 31, 2027. Installed extensions keep running, but you lose updating, reconfiguring and uninstalling. The dated timeline, how to list your extensions, and the migration paths Firebase documents, checked October 18, 2026.",[2319,2322,2325,2328,2331],{"question":2320,"answer":2321},"When does Firebase Extensions shut down?","On March 31, 2027. The Firebase Extensions page says the service is deprecated and will shut down on that date. The FAQ adds that additional migration guidance and tools were due in September 2026, per the FAQ's own wording.",{"question":2323,"answer":2324},"Will my installed extensions stop working on March 31, 2027?","Not on that day. Firebase says already-deployed extensions run on standard Google Cloud infrastructure and continue to execute. What goes away is management: you cannot update, reconfigure or uninstall them through the console or CLI, or download their configuration. Firebase also warns that most extensions use the legacy Cloud Functions v1 SDK, and that they may stop running once older Node.js runtimes are decommissioned.",{"question":2326,"answer":2327},"What does Firebase recommend instead of extensions?","Self-managed function kits. Firebase's first path is an npm-shared kit built on the Cloud Functions v2 SDK and installed through the CLI. Its second path, for extensions with no kit, is to fork the extension source, refactor the triggers into v2 functions and maintain the code yourself.",{"question":2329,"answer":2330},"How do I see which extensions my project has installed?","Run firebase ext:list --project \u003Cproject-id>. Firebase says the output shows the extension, publisher, instance ID, state, version, your last update and a Replacement Kit column. The console Extensions page also shows whether a replacement is available.",{"question":2332,"answer":2333},"What about the Stripe payments extension?","Stripe's Firebase extensions repository says it was archived by its owner on June 18, 2026 and is no longer maintained. It also notes the 2023 transfer of the payments extension to Invertase. That is a repository status, not a Firebase shutdown notice, so check the extension you actually run.",{"readingTimeStats":2335},{"text":566,"minutes":2336,"time":2337,"words":2338},7.76,465600,1552,"\u002Fblog\u002Ffirebase-extensions-shutting-down-replace-2027","firebase extensions shutting down",[574,2342,575],"firebase-studio-shutting-down-migrate-project-2027",{"title":1802,"description":2317},[2345,2347,2349,2350,2353,2356,2359,2362,2365,2368],{"title":2346,"url":1877},"Firebase, Firebase Extensions overview (deprecation notice)",{"title":2348,"url":764},"Firebase, Firebase Extensions deprecation FAQ and troubleshooting",{"title":1072,"url":909},{"title":2351,"url":2352},"Firebase, post-migration best practices","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions\u002Fmigration-best-practices",{"title":2354,"url":2355},"GitHub, firebase\u002Fextensions repository","https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fextensions",{"title":2357,"url":2358},"GitHub, firestore-bigquery-export function kit README","https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fextensions\u002Ftree\u002Fkits\u002Fkits\u002Ffirestore-bigquery-export",{"title":2360,"url":2361},"GitHub, firestore-send-email function kit README","https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fextensions\u002Ftree\u002Fkits\u002Fkits\u002Ffirestore-send-email",{"title":2363,"url":2364},"GitHub, storage-resize-images function kit README","https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fextensions\u002Ftree\u002Fkits\u002Fkits\u002Fstorage-resize-images",{"title":2366,"url":2367},"GitHub, function kits folder in firebase\u002Fextensions","https:\u002F\u002Fgithub.com\u002Ffirebase\u002Fextensions\u002Ftree\u002Fkits\u002Fkits",{"title":2369,"url":1848},"GitHub, Stripe Firebase extensions repository","blog\u002Ffirebase-extensions-shutting-down-replace-2027","firebase extensions shutting down, firebase extensions deprecated, firebase extensions replacement, firebase extensions march 31 2027, firebase ext migrate, firebase function kits, firestore bigquery export kit, trigger email firebase replacement, resize images extension replacement, stripe firebase extension archived",[2373,2374,2375,2376,2377],"The Firebase Extensions service shuts down on March 31, 2027. Firebase says already-installed extensions keep executing, but after that date you cannot update, reconfigure or uninstall them through the console or CLI, or download their configuration.","Firebase names two migration paths: an npm-shared function kit, recommended for Stream Firestore to BigQuery and other kits on npm, or forking the extension source and managing it yourself as Cloud Functions v2.","Run firebase ext:list --project \u003Cproject-id> to see every installed extension. Its output includes a Replacement Kit column, and the migration guide needs firebase-tools 15.32.0 or later.","Most extensions use the legacy Cloud Functions v1 SDK. Firebase warns that functions may stop running or be disabled once Google decommissions the older Node.js runtimes.","Firebase says to save your configuration while you still can, because after March 31, 2027 you cannot fetch it. Uninstall extensions you no longer use before that date.","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-extensions-shutting-down-replace-2027\u002F","F83ZxEQPwFb0459hCMQcQUnGp657rrTS8Dks6m7nj_s",{"id":2381,"title":2382,"author":2383,"body":2385,"category":542,"createdAt":3549,"description":3550,"disclosure":545,"extension":546,"faq":545,"howTo":545,"lastVerified":545,"location":563,"meta":3551,"navigation":346,"ogImage":545,"path":3557,"primaryKeyword":545,"readingTime":3558,"related":545,"seo":3559,"sources":545,"stem":3560,"tags":3561,"takeaways":545,"updatedAt":3562,"url":3563,"__hash__":3564},"blog\u002Fblog\u002Fhow-to-test-firebase-security-rules-2026.md","How to Test Firebase Security Rules with the Emulator (2026)",{"name":7,"social":2384},{"twitter":9},{"type":11,"value":2386,"toc":3533},[2387,2397,2409,2413,2422,2456,2484,2488,2510,2527,2570,2574,2577,2583,2586,3283,3289,3293,3296,3364,3367,3371,3383,3403,3413,3417,3428,3432,3440,3447,3451,3455,3477,3481,3494,3498,3508,3512,3523,3527,3530],[14,2388,2389,2392,2393,2396],{},[17,2390,2391],{},"The only reliable way to know your Firebase Security Rules work is to try to break them, automatically, every time they change."," Reading rules and clicking around the app misses the cases that matter: another user's data, another tenant's data, and a user giving themselves a higher role. The Firebase Emulator Suite and the ",[22,2394,2395],{},"@firebase\u002Frules-unit-testing"," library let you write those attempts as ordinary unit tests that run in seconds and never touch production.",[14,2398,2399,2400,2404,2405,116],{},"This is the technique behind App369's ",[74,2401,2403],{"href":2402},"\u002Ffixed-price\u002Ffirebase-security-rules-audit\u002F","fixed-price Firebase Security Rules Audit",", and the kind of test Simon relies on for the rules in Workspace369, his production Flutter and Firebase SaaS. If you want the rules themselves explained first, start with the ",[74,2406,2408],{"href":2407},"\u002Fblog\u002Ffirebase-security-guide-2026\u002F","Firebase Security Rules guide",[36,2410,2412],{"id":2411},"step-1-install-and-start-the-emulators","Step 1: Install and start the emulators",[14,2414,2415,2416,2421],{},"You need Node.js, a recent Firebase CLI and a Java runtime for the Firestore emulator. The ",[74,2417,2420],{"href":2418,"rel":2419},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Femulator-suite\u002Finstall_and_configure",[78],"install and configure docs"," list the exact minimum versions. Then, in your project:",[194,2423,2427],{"className":2424,"code":2425,"language":2426,"meta":202,"style":202},"language-bash shiki shiki-themes github-light github-dark","firebase init emulators\nfirebase emulators:start --only firestore\n","bash",[22,2428,2429,2442],{"__ignoreMap":202},[322,2430,2431,2435,2439],{"class":324,"line":325},[322,2432,2434],{"class":2433},"sScJk","firebase",[322,2436,2438],{"class":2437},"sZZnC"," init",[322,2440,2441],{"class":2437}," emulators\n",[322,2443,2444,2446,2449,2453],{"class":324,"line":331},[322,2445,2434],{"class":2433},[322,2447,2448],{"class":2437}," emulators:start",[322,2450,2452],{"class":2451},"sj4cs"," --only",[322,2454,2455],{"class":2437}," firestore\n",[14,2457,2458,2461,2462,2465,2466,2469,2470,2473,2474,2479,2480,2483],{},[22,2459,2460],{},"firebase init emulators"," lets you pick emulators and downloads their binaries. By default the Firestore emulator listens on port 8080 and the Emulator UI on port 4000. Make sure ",[22,2463,2464],{},"firebase.json"," points at your rules file, for example ",[22,2467,2468],{},"\"firestore\": { \"rules\": \"firestore.rules\" }",", plus an ",[22,2471,2472],{},"emulators"," block if you want non-default ports. The ",[74,2475,2478],{"href":2476,"rel":2477},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Femulator-suite\u002Fconnect_firestore",[78],"Firestore emulator docs"," also recommend demo project IDs (prefixed ",[22,2481,2482],{},"demo-","): code can't accidentally reach production resources, and no real Firebase project is needed.",[36,2485,2487],{"id":2486},"step-2-set-up-the-test-library","Step 2: Set up the test library",[194,2489,2491],{"className":2424,"code":2490,"language":2426,"meta":202,"style":202},"npm install --save-dev @firebase\u002Frules-unit-testing firebase\n",[22,2492,2493],{"__ignoreMap":202},[322,2494,2495,2498,2501,2504,2507],{"class":324,"line":325},[322,2496,2497],{"class":2433},"npm",[322,2499,2500],{"class":2437}," install",[322,2502,2503],{"class":2451}," --save-dev",[322,2505,2506],{"class":2437}," @firebase\u002Frules-unit-testing",[322,2508,2509],{"class":2437}," firebase\n",[14,2511,2512,2513,2516,2517,2520,2521,2526],{},"The current library (v3) pairs with the modular Firebase JS SDK (v9 and later). You test through ",[22,2514,2515],{},"RulesTestEnvironment",", created with ",[22,2518,2519],{},"initializeTestEnvironment",". The ",[74,2522,2525],{"href":2523,"rel":2524},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Frules\u002Funit-tests",[78],"official unit-test guide"," documents these pieces:",[1895,2528,2529,2535,2545,2551,2560],{},[155,2530,2531,2534],{},[22,2532,2533],{},"initializeTestEnvironment({ projectId, firestore: { rules } })"," creates the environment from your rules text.",[155,2536,2537,2540,2541,2544],{},[22,2538,2539],{},"testEnv.authenticatedContext(uid, tokenOptions)"," acts as a signed-in user; ",[22,2542,2543],{},"testEnv.unauthenticatedContext()"," acts as a signed-out client.",[155,2546,2547,2550],{},[22,2548,2549],{},"testEnv.withSecurityRulesDisabled(callback)"," runs setup code that bypasses rules, so you can seed data.",[155,2552,2553,1648,2556,2559],{},[22,2554,2555],{},"assertSucceeds(promise)",[22,2557,2558],{},"assertFails(promise)"," check whether rules allowed or denied an operation.",[155,2561,2562,2565,2566,2569],{},[22,2563,2564],{},"testEnv.clearFirestore()"," clears data between tests, and ",[22,2567,2568],{},"testEnv.cleanup()"," releases resources when you finish.",[36,2571,2573],{"id":2572},"step-3-write-a-first-test-file","Step 3: Write a first test file",[14,2575,2576],{},"Say your rules let a user read their own profile, create it only as a plain member, and never change their own role:",[194,2578,2581],{"className":2579,"code":2580,"language":199},[197],"rules_version = '2';\nservice cloud.firestore {\n  match \u002Fdatabases\u002F{database}\u002Fdocuments {\n    match \u002Fusers\u002F{uid} {\n      allow read: if request.auth != null && request.auth.uid == uid;\n      allow create: if request.auth != null && request.auth.uid == uid\n        && request.resource.data.role == 'member';\n      allow update: if request.auth != null && request.auth.uid == uid\n        && request.resource.data.role == resource.data.role;\n    }\n  }\n}\n",[22,2582,2580],{"__ignoreMap":202},[14,2584,2585],{},"A Jest-style test file in TypeScript:",[194,2587,2591],{"className":2588,"code":2589,"language":2590,"meta":202,"style":202},"language-ts shiki shiki-themes github-light github-dark","import { readFileSync } from 'fs';\nimport {\n  initializeTestEnvironment,\n  assertFails,\n  assertSucceeds,\n  RulesTestEnvironment,\n} from '@firebase\u002Frules-unit-testing';\nimport { doc, getDoc, setDoc, updateDoc } from 'firebase\u002Ffirestore';\n\nlet testEnv: RulesTestEnvironment;\n\nbeforeAll(async () => {\n  testEnv = await initializeTestEnvironment({\n    projectId: 'demo-rules-test',\n    firestore: {\n      rules: readFileSync('firestore.rules', 'utf8'),\n      host: '127.0.0.1',\n      port: 8080,\n    },\n  });\n});\n\nafterAll(async () => {\n  await testEnv.cleanup();\n});\n\nbeforeEach(async () => {\n  await testEnv.clearFirestore();\n  \u002F\u002F Seed data with rules switched off\n  await testEnv.withSecurityRulesDisabled(async (ctx) => {\n    await setDoc(doc(ctx.firestore(), 'users\u002Falice'), { role: 'member' });\n  });\n});\n\ntest('a user can read their own profile', async () => {\n  const alice = testEnv.authenticatedContext('alice');\n  await assertSucceeds(getDoc(doc(alice.firestore(), 'users\u002Falice')));\n});\n\ntest('a user cannot read someone else\\'s profile', async () => {\n  const bob = testEnv.authenticatedContext('bob');\n  await assertFails(getDoc(doc(bob.firestore(), 'users\u002Falice')));\n});\n\ntest('a signed-out client cannot read anything', async () => {\n  const anon = testEnv.unauthenticatedContext();\n  await assertFails(getDoc(doc(anon.firestore(), 'users\u002Falice')));\n});\n\ntest('a user cannot promote themselves to admin', async () => {\n  const alice = testEnv.authenticatedContext('alice');\n  await assertFails(updateDoc(doc(alice.firestore(), 'users\u002Falice'), { role: 'admin' }));\n});\n","ts",[22,2592,2593,2612,2619,2624,2629,2634,2639,2651,2665,2669,2685,2689,2708,2726,2738,2744,2766,2777,2788,2794,2800,2806,2811,2827,2842,2847,2852,2868,2880,2887,2915,2950,2955,2960,2965,2986,3011,3040,3045,3050,3076,3097,3124,3129,3134,3154,3171,3197,3202,3207,3227,3246,3278],{"__ignoreMap":202},[322,2594,2595,2599,2603,2606,2609],{"class":324,"line":325},[322,2596,2598],{"class":2597},"szBVR","import",[322,2600,2602],{"class":2601},"sVt8B"," { readFileSync } ",[322,2604,2605],{"class":2597},"from",[322,2607,2608],{"class":2437}," 'fs'",[322,2610,2611],{"class":2601},";\n",[322,2613,2614,2616],{"class":324,"line":331},[322,2615,2598],{"class":2597},[322,2617,2618],{"class":2601}," {\n",[322,2620,2621],{"class":324,"line":337},[322,2622,2623],{"class":2601},"  initializeTestEnvironment,\n",[322,2625,2626],{"class":324,"line":343},[322,2627,2628],{"class":2601},"  assertFails,\n",[322,2630,2631],{"class":324,"line":205},[322,2632,2633],{"class":2601},"  assertSucceeds,\n",[322,2635,2636],{"class":324,"line":355},[322,2637,2638],{"class":2601},"  RulesTestEnvironment,\n",[322,2640,2641,2644,2646,2649],{"class":324,"line":361},[322,2642,2643],{"class":2601},"} ",[322,2645,2605],{"class":2597},[322,2647,2648],{"class":2437}," '@firebase\u002Frules-unit-testing'",[322,2650,2611],{"class":2601},[322,2652,2653,2655,2658,2660,2663],{"class":324,"line":367},[322,2654,2598],{"class":2597},[322,2656,2657],{"class":2601}," { doc, getDoc, setDoc, updateDoc } ",[322,2659,2605],{"class":2597},[322,2661,2662],{"class":2437}," 'firebase\u002Ffirestore'",[322,2664,2611],{"class":2601},[322,2666,2667],{"class":324,"line":373},[322,2668,347],{"emptyLinePlaceholder":346},[322,2670,2671,2674,2677,2680,2683],{"class":324,"line":379},[322,2672,2673],{"class":2597},"let",[322,2675,2676],{"class":2601}," testEnv",[322,2678,2679],{"class":2597},":",[322,2681,2682],{"class":2433}," RulesTestEnvironment",[322,2684,2611],{"class":2601},[322,2686,2687],{"class":324,"line":385},[322,2688,347],{"emptyLinePlaceholder":346},[322,2690,2691,2694,2697,2700,2703,2706],{"class":324,"line":391},[322,2692,2693],{"class":2433},"beforeAll",[322,2695,2696],{"class":2601},"(",[322,2698,2699],{"class":2597},"async",[322,2701,2702],{"class":2601}," () ",[322,2704,2705],{"class":2597},"=>",[322,2707,2618],{"class":2601},[322,2709,2711,2714,2717,2720,2723],{"class":324,"line":2710},13,[322,2712,2713],{"class":2601},"  testEnv ",[322,2715,2716],{"class":2597},"=",[322,2718,2719],{"class":2597}," await",[322,2721,2722],{"class":2433}," initializeTestEnvironment",[322,2724,2725],{"class":2601},"({\n",[322,2727,2729,2732,2735],{"class":324,"line":2728},14,[322,2730,2731],{"class":2601},"    projectId: ",[322,2733,2734],{"class":2437},"'demo-rules-test'",[322,2736,2737],{"class":2601},",\n",[322,2739,2741],{"class":324,"line":2740},15,[322,2742,2743],{"class":2601},"    firestore: {\n",[322,2745,2747,2750,2753,2755,2758,2760,2763],{"class":324,"line":2746},16,[322,2748,2749],{"class":2601},"      rules: ",[322,2751,2752],{"class":2433},"readFileSync",[322,2754,2696],{"class":2601},[322,2756,2757],{"class":2437},"'firestore.rules'",[322,2759,967],{"class":2601},[322,2761,2762],{"class":2437},"'utf8'",[322,2764,2765],{"class":2601},"),\n",[322,2767,2769,2772,2775],{"class":324,"line":2768},17,[322,2770,2771],{"class":2601},"      host: ",[322,2773,2774],{"class":2437},"'127.0.0.1'",[322,2776,2737],{"class":2601},[322,2778,2780,2783,2786],{"class":324,"line":2779},18,[322,2781,2782],{"class":2601},"      port: ",[322,2784,2785],{"class":2451},"8080",[322,2787,2737],{"class":2601},[322,2789,2791],{"class":324,"line":2790},19,[322,2792,2793],{"class":2601},"    },\n",[322,2795,2797],{"class":324,"line":2796},20,[322,2798,2799],{"class":2601},"  });\n",[322,2801,2803],{"class":324,"line":2802},21,[322,2804,2805],{"class":2601},"});\n",[322,2807,2809],{"class":324,"line":2808},22,[322,2810,347],{"emptyLinePlaceholder":346},[322,2812,2814,2817,2819,2821,2823,2825],{"class":324,"line":2813},23,[322,2815,2816],{"class":2433},"afterAll",[322,2818,2696],{"class":2601},[322,2820,2699],{"class":2597},[322,2822,2702],{"class":2601},[322,2824,2705],{"class":2597},[322,2826,2618],{"class":2601},[322,2828,2830,2833,2836,2839],{"class":324,"line":2829},24,[322,2831,2832],{"class":2597},"  await",[322,2834,2835],{"class":2601}," testEnv.",[322,2837,2838],{"class":2433},"cleanup",[322,2840,2841],{"class":2601},"();\n",[322,2843,2845],{"class":324,"line":2844},25,[322,2846,2805],{"class":2601},[322,2848,2850],{"class":324,"line":2849},26,[322,2851,347],{"emptyLinePlaceholder":346},[322,2853,2855,2858,2860,2862,2864,2866],{"class":324,"line":2854},27,[322,2856,2857],{"class":2433},"beforeEach",[322,2859,2696],{"class":2601},[322,2861,2699],{"class":2597},[322,2863,2702],{"class":2601},[322,2865,2705],{"class":2597},[322,2867,2618],{"class":2601},[322,2869,2871,2873,2875,2878],{"class":324,"line":2870},28,[322,2872,2832],{"class":2597},[322,2874,2835],{"class":2601},[322,2876,2877],{"class":2433},"clearFirestore",[322,2879,2841],{"class":2601},[322,2881,2883],{"class":324,"line":2882},29,[322,2884,2886],{"class":2885},"sJ8bj","  \u002F\u002F Seed data with rules switched off\n",[322,2888,2890,2892,2894,2897,2899,2901,2904,2908,2911,2913],{"class":324,"line":2889},30,[322,2891,2832],{"class":2597},[322,2893,2835],{"class":2601},[322,2895,2896],{"class":2433},"withSecurityRulesDisabled",[322,2898,2696],{"class":2601},[322,2900,2699],{"class":2597},[322,2902,2903],{"class":2601}," (",[322,2905,2907],{"class":2906},"s4XuR","ctx",[322,2909,2910],{"class":2601},") ",[322,2912,2705],{"class":2597},[322,2914,2618],{"class":2601},[322,2916,2918,2921,2924,2926,2929,2932,2935,2938,2941,2944,2947],{"class":324,"line":2917},31,[322,2919,2920],{"class":2597},"    await",[322,2922,2923],{"class":2433}," setDoc",[322,2925,2696],{"class":2601},[322,2927,2928],{"class":2433},"doc",[322,2930,2931],{"class":2601},"(ctx.",[322,2933,2934],{"class":2433},"firestore",[322,2936,2937],{"class":2601},"(), ",[322,2939,2940],{"class":2437},"'users\u002Falice'",[322,2942,2943],{"class":2601},"), { role: ",[322,2945,2946],{"class":2437},"'member'",[322,2948,2949],{"class":2601}," });\n",[322,2951,2953],{"class":324,"line":2952},32,[322,2954,2799],{"class":2601},[322,2956,2958],{"class":324,"line":2957},33,[322,2959,2805],{"class":2601},[322,2961,2963],{"class":324,"line":2962},34,[322,2964,347],{"emptyLinePlaceholder":346},[322,2966,2968,2971,2973,2976,2978,2980,2982,2984],{"class":324,"line":2967},35,[322,2969,2970],{"class":2433},"test",[322,2972,2696],{"class":2601},[322,2974,2975],{"class":2437},"'a user can read their own profile'",[322,2977,967],{"class":2601},[322,2979,2699],{"class":2597},[322,2981,2702],{"class":2601},[322,2983,2705],{"class":2597},[322,2985,2618],{"class":2601},[322,2987,2989,2992,2995,2998,3000,3003,3005,3008],{"class":324,"line":2988},36,[322,2990,2991],{"class":2597},"  const",[322,2993,2994],{"class":2451}," alice",[322,2996,2997],{"class":2597}," =",[322,2999,2835],{"class":2601},[322,3001,3002],{"class":2433},"authenticatedContext",[322,3004,2696],{"class":2601},[322,3006,3007],{"class":2437},"'alice'",[322,3009,3010],{"class":2601},");\n",[322,3012,3014,3016,3019,3021,3024,3026,3028,3031,3033,3035,3037],{"class":324,"line":3013},37,[322,3015,2832],{"class":2597},[322,3017,3018],{"class":2433}," assertSucceeds",[322,3020,2696],{"class":2601},[322,3022,3023],{"class":2433},"getDoc",[322,3025,2696],{"class":2601},[322,3027,2928],{"class":2433},[322,3029,3030],{"class":2601},"(alice.",[322,3032,2934],{"class":2433},[322,3034,2937],{"class":2601},[322,3036,2940],{"class":2437},[322,3038,3039],{"class":2601},")));\n",[322,3041,3043],{"class":324,"line":3042},38,[322,3044,2805],{"class":2601},[322,3046,3048],{"class":324,"line":3047},39,[322,3049,347],{"emptyLinePlaceholder":346},[322,3051,3053,3055,3057,3060,3063,3066,3068,3070,3072,3074],{"class":324,"line":3052},40,[322,3054,2970],{"class":2433},[322,3056,2696],{"class":2601},[322,3058,3059],{"class":2437},"'a user cannot read someone else",[322,3061,3062],{"class":2451},"\\'",[322,3064,3065],{"class":2437},"s profile'",[322,3067,967],{"class":2601},[322,3069,2699],{"class":2597},[322,3071,2702],{"class":2601},[322,3073,2705],{"class":2597},[322,3075,2618],{"class":2601},[322,3077,3079,3081,3084,3086,3088,3090,3092,3095],{"class":324,"line":3078},41,[322,3080,2991],{"class":2597},[322,3082,3083],{"class":2451}," bob",[322,3085,2997],{"class":2597},[322,3087,2835],{"class":2601},[322,3089,3002],{"class":2433},[322,3091,2696],{"class":2601},[322,3093,3094],{"class":2437},"'bob'",[322,3096,3010],{"class":2601},[322,3098,3100,3102,3105,3107,3109,3111,3113,3116,3118,3120,3122],{"class":324,"line":3099},42,[322,3101,2832],{"class":2597},[322,3103,3104],{"class":2433}," assertFails",[322,3106,2696],{"class":2601},[322,3108,3023],{"class":2433},[322,3110,2696],{"class":2601},[322,3112,2928],{"class":2433},[322,3114,3115],{"class":2601},"(bob.",[322,3117,2934],{"class":2433},[322,3119,2937],{"class":2601},[322,3121,2940],{"class":2437},[322,3123,3039],{"class":2601},[322,3125,3127],{"class":324,"line":3126},43,[322,3128,2805],{"class":2601},[322,3130,3132],{"class":324,"line":3131},44,[322,3133,347],{"emptyLinePlaceholder":346},[322,3135,3137,3139,3141,3144,3146,3148,3150,3152],{"class":324,"line":3136},45,[322,3138,2970],{"class":2433},[322,3140,2696],{"class":2601},[322,3142,3143],{"class":2437},"'a signed-out client cannot read anything'",[322,3145,967],{"class":2601},[322,3147,2699],{"class":2597},[322,3149,2702],{"class":2601},[322,3151,2705],{"class":2597},[322,3153,2618],{"class":2601},[322,3155,3157,3159,3162,3164,3166,3169],{"class":324,"line":3156},46,[322,3158,2991],{"class":2597},[322,3160,3161],{"class":2451}," anon",[322,3163,2997],{"class":2597},[322,3165,2835],{"class":2601},[322,3167,3168],{"class":2433},"unauthenticatedContext",[322,3170,2841],{"class":2601},[322,3172,3174,3176,3178,3180,3182,3184,3186,3189,3191,3193,3195],{"class":324,"line":3173},47,[322,3175,2832],{"class":2597},[322,3177,3104],{"class":2433},[322,3179,2696],{"class":2601},[322,3181,3023],{"class":2433},[322,3183,2696],{"class":2601},[322,3185,2928],{"class":2433},[322,3187,3188],{"class":2601},"(anon.",[322,3190,2934],{"class":2433},[322,3192,2937],{"class":2601},[322,3194,2940],{"class":2437},[322,3196,3039],{"class":2601},[322,3198,3200],{"class":324,"line":3199},48,[322,3201,2805],{"class":2601},[322,3203,3205],{"class":324,"line":3204},49,[322,3206,347],{"emptyLinePlaceholder":346},[322,3208,3210,3212,3214,3217,3219,3221,3223,3225],{"class":324,"line":3209},50,[322,3211,2970],{"class":2433},[322,3213,2696],{"class":2601},[322,3215,3216],{"class":2437},"'a user cannot promote themselves to admin'",[322,3218,967],{"class":2601},[322,3220,2699],{"class":2597},[322,3222,2702],{"class":2601},[322,3224,2705],{"class":2597},[322,3226,2618],{"class":2601},[322,3228,3230,3232,3234,3236,3238,3240,3242,3244],{"class":324,"line":3229},51,[322,3231,2991],{"class":2597},[322,3233,2994],{"class":2451},[322,3235,2997],{"class":2597},[322,3237,2835],{"class":2601},[322,3239,3002],{"class":2433},[322,3241,2696],{"class":2601},[322,3243,3007],{"class":2437},[322,3245,3010],{"class":2601},[322,3247,3249,3251,3253,3255,3258,3260,3262,3264,3266,3268,3270,3272,3275],{"class":324,"line":3248},52,[322,3250,2832],{"class":2597},[322,3252,3104],{"class":2433},[322,3254,2696],{"class":2601},[322,3256,3257],{"class":2433},"updateDoc",[322,3259,2696],{"class":2601},[322,3261,2928],{"class":2433},[322,3263,3030],{"class":2601},[322,3265,2934],{"class":2433},[322,3267,2937],{"class":2601},[322,3269,2940],{"class":2437},[322,3271,2943],{"class":2601},[322,3273,3274],{"class":2437},"'admin'",[322,3276,3277],{"class":2601}," }));\n",[322,3279,3281],{"class":324,"line":3280},53,[322,3282,2805],{"class":2601},[14,3284,3285,3286,3288],{},"Run it while the emulator is up, with your usual test runner. The seed step matters: tests that depend on existing documents must create them with ",[22,3287,2896],{},", otherwise your own rules block the setup.",[36,3290,3292],{"id":3291},"step-4-decide-what-to-test","Step 4: Decide what to test",[14,3294,3295],{},"Passing tests for the happy path prove little. Write the attacks:",[152,3297,3298,3304,3310,3326,3332,3341,3358],{},[155,3299,3300,3303],{},[17,3301,3302],{},"Cross-user reads and writes."," User B reading, updating and deleting user A's documents, in every collection that holds user data.",[155,3305,3306,3309],{},[17,3307,3308],{},"Cross-tenant access."," If you have workspaces, teams or organizations, a member of tenant 1 must fail to read or write tenant 2's documents, including sub-collections. Seed two tenants and test both directions.",[155,3311,3312,3315,3316,967,3319,2046,3322,3325],{},[17,3313,3314],{},"Role escalation."," A user writing their own ",[22,3317,3318],{},"role",[22,3320,3321],{},"isAdmin",[22,3323,3324],{},"plan"," field on create and on update. Also test adding themselves to another tenant's member list.",[155,3327,3328,3331],{},[17,3329,3330],{},"Field-level validation."," Creates with missing or extra fields, wrong types, oversized strings, and fields the client should never set, such as server-owned timestamps or counters.",[155,3333,3334,3337,3338,116],{},[17,3335,3336],{},"Signed-out access."," Every path with ",[22,3339,3340],{},"unauthenticatedContext()",[155,3342,3343,3346,3347,3350,3351,3353,3354,3357],{},[17,3344,3345],{},"Storage paths."," The same user and tenant checks against Storage rules. Pass ",[22,3348,3349],{},"storage: { rules }"," to ",[22,3352,2519],{}," and use ",[22,3355,3356],{},"ctx.storage()"," in the tests.",[155,3359,3360,3363],{},[17,3361,3362],{},"Queries, not just single reads."," A rule that allows reading one document can still reject a list query that isn't constrained to what the rule permits. Test the exact query your app runs.",[14,3365,3366],{},"For each tenant-isolation rule, write one test that should succeed and at least one that should fail. If you can't make a failing test fail, you have found a hole.",[36,3368,3370],{"id":3369},"step-5-run-it-in-ci","Step 5: Run it in CI",[14,3372,3373,3376,3377,3382],{},[22,3374,3375],{},"firebase emulators:exec"," starts the emulators, runs your command, and shuts them down when the command ends. The ",[74,3378,3381],{"href":3379,"rel":3380},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Femulator-suite\u002Fconnect_and_prototype",[78],"emulator docs"," describe it as the way to run scripted tests, and it suits continuous integration:",[194,3384,3386],{"className":2424,"code":3385,"language":2426,"meta":202,"style":202},"firebase emulators:exec --only firestore \"npm test\"\n",[22,3387,3388],{"__ignoreMap":202},[322,3389,3390,3392,3395,3397,3400],{"class":324,"line":325},[322,3391,2434],{"class":2433},[322,3393,3394],{"class":2437}," emulators:exec",[322,3396,2452],{"class":2451},[322,3398,3399],{"class":2437}," firestore",[322,3401,3402],{"class":2437}," \"npm test\"\n",[14,3404,3405,3406,967,3409,3412],{},"The Firestore emulator clears its data when it shuts down, so every CI run starts clean. Cache the emulator download between CI runs if your provider supports it, and add the Java runtime to the CI image. Make the rules test a required check for any pull request that touches ",[22,3407,3408],{},"firestore.rules",[22,3410,3411],{},"storage.rules"," or the tests.",[36,3414,3416],{"id":3415},"step-6-debug-with-the-request-monitor","Step 6: Debug with the request monitor",[14,3418,3419,3420,3423,3424,3427],{},"When a test fails and you don't know which rule caused it, run ",[22,3421,3422],{},"firebase emulators:start",", point a manual client at it, and open the Emulator UI at ",[22,3425,3426],{},"http:\u002F\u002Flocalhost:4000",". In the Firestore section, the Requests tab shows each request and traces how your rules were evaluated, which line allowed or denied it. The Firestore emulator docs describe this request monitoring. It is the fastest way to find out that a rule you thought applied never matched.",[36,3429,3431],{"id":3430},"when-to-get-help","When to get help",[14,3433,3434,3435,3439],{},"Before you write tests, a quick first pass helps: paste your rules into the free ",[74,3436,3438],{"href":3437},"\u002Ftools\u002Ffirebase-rules-checker\u002F","Firebase Security Rules checker"," to spot public paths, test-mode rules and sign-in-only checks. It runs in your browser.",[14,3441,3442,3443,3446],{},"If you don't have the time to build the model of who should access what, or you have already found a hole and want the fixes reviewed, App369's ",[74,3444,3445],{"href":2402},"fixed-price Firebase Security Rules Audit + Fix PR"," is $950 and delivered in 5 business days. It covers Firestore and Storage rules plus up to 15 Cloud Functions in one Firebase project, and you get a written role and tenant access model, an emulator test suite for cross-user, cross-tenant and role-escalation attempts, a severity-ranked report and a pull request with fixes that passes the suite. It runs on the emulator or test data only, and it is a technical review, not a compliance certificate.",[36,3448,3450],{"id":3449},"frequently-asked-questions","Frequently Asked Questions",[244,3452,3454],{"id":3453},"how-do-i-test-firestore-security-rules-locally","How do I test Firestore security rules locally?",[14,3456,3457,3458,3461,3462,3464,3465,3467,3468,3470,3471,1648,3474,116],{},"Run the Firestore emulator with ",[22,3459,3460],{},"firebase emulators:start --only firestore",", then write tests with ",[22,3463,2395],{},". Create a test environment with ",[22,3466,2519],{},", act as users with ",[22,3469,3002],{},", and check results with ",[22,3472,3473],{},"assertSucceeds",[22,3475,3476],{},"assertFails",[244,3478,3480],{"id":3479},"can-i-test-firebase-storage-rules-the-same-way","Can I test Firebase Storage rules the same way?",[14,3482,3483,3484,3486,3487,3489,3490,3493],{},"Yes. Pass a ",[22,3485,3349],{}," option to ",[22,3488,2519],{},", start the Storage emulator, and perform uploads and downloads through the context's ",[22,3491,3492],{},"storage()"," client. The same assertions apply.",[244,3495,3497],{"id":3496},"how-do-i-run-firebase-rules-tests-in-ci","How do I run Firebase rules tests in CI?",[14,3499,3500,3501,3503,3504,3507],{},"Use ",[22,3502,3375],{}," to start the emulators, run your test command and stop them. For example, ",[22,3505,3506],{},"firebase emulators:exec --only firestore \"npm test\"",". The CI machine needs Node.js, the Firebase CLI and a Java runtime.",[244,3509,3511],{"id":3510},"how-do-i-add-test-data-when-my-rules-would-block-it","How do I add test data when my rules would block it?",[14,3513,3514,3515,3518,3519,3522],{},"Call ",[22,3516,3517],{},"testEnv.withSecurityRulesDisabled(async (ctx) => { ... })"," and write documents through ",[22,3520,3521],{},"ctx.firestore()",". Rules are skipped inside that callback only.",[244,3524,3526],{"id":3525},"does-passing-rules-tests-mean-my-app-is-secure","Does passing rules tests mean my app is secure?",[14,3528,3529],{},"No. Tests show your rules behave as you described them, so they are only as good as the cases you wrote. They don't cover Cloud Functions logic, leaked credentials or anything outside Firebase.",[524,3531,3532],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":202,"searchDepth":331,"depth":331,"links":3534},[3535,3536,3537,3538,3539,3540,3541,3542],{"id":2411,"depth":331,"text":2412},{"id":2486,"depth":331,"text":2487},{"id":2572,"depth":331,"text":2573},{"id":3291,"depth":331,"text":3292},{"id":3369,"depth":331,"text":3370},{"id":3415,"depth":331,"text":3416},{"id":3430,"depth":331,"text":3431},{"id":3449,"depth":331,"text":3450,"children":3543},[3544,3545,3546,3547,3548],{"id":3453,"depth":337,"text":3454},{"id":3479,"depth":337,"text":3480},{"id":3496,"depth":337,"text":3497},{"id":3510,"depth":337,"text":3511},{"id":3525,"depth":337,"text":3526},"2026-10-12T18:00:00.000Z","Unit test Firestore and Storage Security Rules with the Firebase Emulator Suite and @firebase\u002Frules-unit-testing: setup, a TypeScript example, what to test, and CI.",{"readingTimeStats":3552},{"text":3553,"minutes":3554,"time":3555,"words":3556},"7 min read",6.31,378600,1262,"\u002Fblog\u002Fhow-to-test-firebase-security-rules-2026","7 min",{"title":2382,"description":3550},"blog\u002Fhow-to-test-firebase-security-rules-2026","firebase security rules testing, firestore rules unit test, firebase emulator, rules-unit-testing, firebase emulators exec, firestore security, storage rules","2026-10-12T20:00:00.000Z","https:\u002F\u002Fapp369.com\u002Fblog\u002Fhow-to-test-firebase-security-rules-2026\u002F","a01k86M8jw17jivJI9coteracbSYds6lfTq1mvRWa54",[3566,3568,3571,3572,3575,3576],{"keyword":5,"url":614,"title":5,"relevance":3567},73,{"keyword":3569,"url":3570,"title":3569,"relevance":2746},"Firebase Test Lab Shutting Down: Alternatives for 2027","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-test-lab-shutting-down-alternatives-2027\u002F",{"keyword":619,"url":1086,"title":619,"relevance":2746},{"keyword":3573,"url":3574,"title":3573,"relevance":2728},"Firebase Studio Shutting Down: How to Migrate by March 2027","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-studio-shutting-down-migrate-project-2027\u002F",{"keyword":1802,"url":2378,"title":1802,"relevance":379},{"keyword":3577,"url":3578,"title":3577,"relevance":373},"Flutter \"Deleted Android v1 Embedding\" Build Error: The Fix","https:\u002F\u002Fapp369.com\u002Fblog\u002Fflutter-deleted-android-v1-embedding-build-failed-2026\u002F",1792383090356]