[{"data":1,"prerenderedAt":2264},["ShallowReactive",2],{"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026\u002F":3,"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026\u002F-related":485,"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026\u002F-resources":2257},{"id":4,"title":5,"author":6,"body":10,"category":418,"createdAt":419,"description":420,"disclosure":421,"extension":422,"faq":423,"howTo":421,"location":442,"meta":443,"navigation":449,"ogImage":421,"path":450,"primaryKeyword":451,"readingTime":452,"related":453,"seo":457,"sources":458,"stem":475,"tags":476,"takeaways":477,"updatedAt":419,"url":483,"__hash__":484},"blog\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026.md","Firebase Deprecations: Every Shutdown Date, 2024 to 2027",{"name":7,"social":8},"Simon Dziak",{"twitter":9},"@SzymonDziak",{"type":11,"value":12,"toc":403},"minimark",[13,21,24,30,35,246,250,255,258,261,265,268,271,274,308,312,315,319,329,333,336,340,386,390],[14,15,16,20],"p",{},[17,18,19],"strong",{},"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,22,23],{},"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,25,26,29],{},[17,27,28],{},"Disclosure:"," 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.",[31,32,34],"h2",{"id":33},"every-firebase-shutdown-in-date-order","Every Firebase shutdown, in date order",[36,37,38,60],"table",{},[39,40,41],"thead",{},[42,43,44,48,51,54,57],"tr",{},[45,46,47],"th",{},"Deadline",[45,49,50],{},"What is retired",[45,52,53],{},"What stops working",[45,55,56],{},"Move to",[45,58,59],{},"Source",[61,62,63,100,126,148,170,192,224],"tbody",{},[42,64,65,73,76,84,92],{},[66,67,68,69,72],"td",{},"From ",[17,70,71],{},"July 22, 2024"," (done)",[66,74,75],{},"Legacy FCM HTTP and XMPP send APIs",[66,77,78,79,83],{},"Sending with a server key to ",[80,81,82],"code",{},"fcm\u002Fsend",". Deprecated June 20, 2023",[66,85,86,87],{},"FCM HTTP v1 API or the Admin SDK. ",[88,89,91],"a",{"href":90},"\u002Fblog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026\u002F","My guide",[66,93,94],{},[88,95,99],{"href":96,"rel":97},"https:\u002F\u002Fweb.archive.org\u002Fweb\u002F20260108211426\u002Fhttps:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fmigrate-v1",[98],"nofollow","Firebase (archived)",[42,101,102,107,110,113,119],{},[66,103,104,72],{},[17,105,106],{},"August 25, 2025",[66,108,109],{},"Firebase Dynamic Links",[66,111,112],{},"Dynamic Links, and email link sign-in that relied on them",[66,114,115,116],{},"Your own deep links. For email link sign-in, Firebase Authentication Android SDK 23.2.0 or later (BoM 33.9.0 or later). ",[88,117,91],{"href":118},"\u002Fblog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026\u002F",[66,120,121],{},[88,122,125],{"href":123,"rel":124},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fauth\u002Fandroid\u002Femail-link-migration",[98],"Firebase",[42,127,128,133,136,139,142],{},[66,129,130],{},[17,131,132],{},"March 22, 2027",[66,134,135],{},"Firebase Studio",[66,137,138],{},"Existing workspaces. New workspaces and signups already stopped on June 22, 2026",[66,140,141],{},"Google AI Studio, Google Antigravity, or an export of your source to another platform",[66,143,144],{},[88,145,125],{"href":146,"rel":147},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fstudio\u002Fmigrating-project",[98],[42,149,150,155,158,161,164],{},[66,151,152],{},[17,153,154],{},"March 31, 2027",[66,156,157],{},"Firebase Extensions",[66,159,160],{},"Updating, reconfiguring or uninstalling extensions, or downloading their configuration, through the console or CLI. Installed extensions keep running",[66,162,163],{},"Function kits on npm where the publisher offers one, or your own Cloud Functions (2nd gen)",[66,165,166],{},[88,167,125],{"href":168,"rel":169},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions\u002Ffaq-and-troubleshooting",[98],[42,171,172,177,180,183,186],{},[66,173,174],{},[17,175,176],{},"June 15, 2027",[66,178,179],{},"Firebase ML custom model hosting",[66,181,182],{},"Hosting and serving custom models through Firebase ML",[66,184,185],{},"Cloud Storage for Firebase, per Firebase's guide",[66,187,188],{},[88,189,125],{"href":190,"rel":191},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fml\u002Fmigrate-to-cloud-storage",[98],[42,193,194,199,202,209,218],{},[66,195,196],{},[17,197,198],{},"September 29, 2027",[66,200,201],{},"FCM InstanceId server APIs and device groups",[66,203,204,205,208],{},"Requests to ",[80,206,207],{},"iid.googleapis.com"," and device group management start failing. New users are blocked after January 1, 2027",[66,210,211,212,215,216],{},"The FCM topic subscription API, HTTP v1 with ",[80,213,214],{},"validate_only",", and sends to individual tokens. ",[88,217,91],{"href":90},[66,219,220],{},[88,221,125],{"href":222,"rel":223},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Ftroubleshooting#fcm-26-deprecation",[98],[42,225,226,231,234,237,240],{},[66,227,228],{},[17,229,230],{},"September 30, 2027",[66,232,233],{},"Firebase Test Lab",[66,235,236],{},"All of Test Lab",[66,238,239],{},"The Developer Device Platform on Google Cloud",[66,241,242],{},[88,243,125],{"href":244,"rel":245},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Ftest-lab",[98],[31,247,249],{"id":248},"what-each-2027-deadline-means-in-practice","What each 2027 deadline means in practice",[251,252,254],"h3",{"id":253},"firebase-studio-march-22-2027","Firebase Studio: March 22, 2027",[14,256,257],{},"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,259,260],{},"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.",[251,262,264],{"id":263},"firebase-extensions-march-31-2027","Firebase Extensions: March 31, 2027",[14,266,267],{},"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,269,270],{},"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,272,273],{},"Before March 31, 2027:",[275,276,277,284,290,296],"ol",{},[278,279,280,283],"li",{},[17,281,282],{},"List what's installed."," In the Firebase console, open Extensions for each project, including staging and old projects.",[278,285,286,289],{},[17,287,288],{},"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.",[278,291,292,295],{},[17,293,294],{},"Export the configuration of the rest."," You need the parameters to set up a replacement.",[278,297,298,301,302,307],{},[17,299,300],{},"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 ",[88,303,306],{"href":304,"rel":305},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fextensions\u002Fusers\u002Fmigrate",[98],"guide for users"," covers both.",[251,309,311],{"id":310},"firebase-ml-model-hosting-june-15-2027","Firebase ML model hosting: June 15, 2027",[14,313,314],{},"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.",[251,316,318],{"id":317},"fcm-instanceid-apis-and-device-groups-september-29-2027","FCM InstanceId APIs and device groups: September 29, 2027",[14,320,321,322,324,325,328],{},"If your server checks tokens with ",[80,323,207],{},", 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 ",[88,326,327],{"href":90},"FCM guide",".",[251,330,332],{"id":331},"test-lab-september-30-2027","Test Lab: September 30, 2027",[14,334,335],{},"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.",[31,337,339],{"id":338},"a-one-hour-check-for-your-project","A one-hour check for your project",[275,341,342,368,374,380],{},[278,343,344,347,348,350,351,350,354,350,357,360,361,364,365,328],{},[17,345,346],{},"Search your code"," for ",[80,349,207],{},", ",[80,352,353],{},"fcm.googleapis.com\u002Ffcm\u002F",[80,355,356],{},"page.link",[80,358,359],{},"firebase-ml-modeldownloader"," (or ",[80,362,363],{},"firebase_ml_model_downloader"," in Flutter), and ",[80,366,367],{},"gcloud firebase test",[278,369,370,373],{},[17,371,372],{},"Open the Firebase console"," for every project you own and look at Extensions, Machine Learning, Test Lab and Studio.",[278,375,376,379],{},[17,377,378],{},"Write down each deadline"," that applies, with the owner of the fix and a target date at least a month early.",[278,381,382,385],{},[17,383,384],{},"Start with the earliest deadlines."," Of the 2027 ones, Studio and Extensions come first, in March.",[31,387,389],{"id":388},"need-a-hand","Need a hand?",[14,391,392,393,397,398,402],{},"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 ",[88,394,396],{"href":395},"\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. If you want help planning several migrations at once, ",[88,399,401],{"href":400},"\u002Fcontact\u002F","send me a short description"," of your project.",{"title":404,"searchDepth":405,"depth":405,"links":406},"",2,[407,408,416,417],{"id":33,"depth":405,"text":34},{"id":248,"depth":405,"text":249,"children":409},[410,412,413,414,415],{"id":253,"depth":411,"text":254},3,{"id":263,"depth":411,"text":264},{"id":310,"depth":411,"text":311},{"id":317,"depth":411,"text":318},{"id":331,"depth":411,"text":332},{"id":338,"depth":405,"text":339},{"id":388,"depth":405,"text":389},"AI & Technology","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.",null,"md",[424,427,430,433,436,439],{"question":425,"answer":426},"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":428,"answer":429},"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":431,"answer":432},"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":434,"answer":435},"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":437,"answer":438},"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":440,"answer":441},"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.","Boynton Beach, FL",{"readingTimeStats":444},{"text":445,"minutes":446,"time":447,"words":448},"6 min read",5.255,315300,1051,true,"\u002Fblog\u002Ffirebase-deprecations-shutdown-dates-2026","firebase deprecations","8 min",[454,455,456],"fcm-legacy-api-shutdown-http-v1-migration-2026","firebase-dynamic-links-shutdown-deep-linking-2026","how-to-cut-your-firebase-bill-2026",{"title":5,"description":420},[459,461,463,465,467,469,471,473],{"title":460,"url":96},"Firebase, migrate from legacy FCM APIs to HTTP v1 (Wayback Machine copy, January 8, 2026)",{"title":462,"url":123},"Firebase, migrating email link sign-in off Dynamic Links (Android)",{"title":464,"url":146},"Firebase, Firebase Studio sunset and project migration",{"title":466,"url":168},"Firebase, Firebase Extensions deprecation FAQ",{"title":468,"url":304},"Firebase, migrate an extension to Cloud Functions as a user",{"title":470,"url":190},"Firebase, migrate custom models from Firebase ML to Cloud Storage",{"title":472,"url":222},"Firebase, FCM InstanceId API and device group deprecation (FAQ, announced September 2026)",{"title":474,"url":244},"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",[478,479,480,481,482],"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","iqe7_rdKT5YLVNZFpSyM8FRIxPr_4--3wAp_MkpS6EE",[486,948,1766],{"id":487,"title":488,"author":489,"body":491,"category":418,"createdAt":887,"description":888,"disclosure":421,"extension":422,"faq":889,"howTo":421,"location":442,"meta":908,"navigation":449,"ogImage":421,"path":914,"primaryKeyword":915,"readingTime":452,"related":916,"seo":919,"sources":920,"stem":938,"tags":939,"takeaways":940,"updatedAt":887,"url":946,"__hash__":947},"blog\u002Fblog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026.md","FCM Legacy API Shutdown: Fixing Push and the 2027 Deadline",{"name":7,"social":490},{"twitter":9},{"type":11,"value":492,"toc":879},[493,499,502,507,511,600,603,607,610,646,650,748,752,755,861,864,866],[14,494,495,498],{},[17,496,497],{},"If your app's push notifications stopped arriving in mid-2024, your server was probably still using the legacy FCM API, which Firebase began shutting down on July 22, 2024."," The fix is on the server: send through the FCM HTTP v1 API, ideally with the Firebase Admin SDK, and replace the old server key with a service account. Then check the second deadline: the InstanceId server APIs and device groups stop working after September 29, 2027.",[14,500,501],{},"If you landed here from a tutorial that links to Firebase's old migration guide, that page now returns 404. The dates and steps here come from Firebase's own documentation, as listed in the sources, including an archived copy of that guide. I tested the old endpoint and guide URL myself on October 18, 2026.",[14,503,504,506],{},[17,505,28],{}," App369 is my studio. I build and fix Flutter and Firebase apps for a living, including push notifications, and the last section mentions what I sell. Google doesn't pay me for anything on this page.",[31,508,510],{"id":509},"what-changed-and-when","What changed, and when",[36,512,513,525],{},[39,514,515],{},[42,516,517,520,523],{},[45,518,519],{},"Date",[45,521,522],{},"What happened",[45,524,59],{},[61,526,527,541,557,571,584],{},[42,528,529,532,535],{},[66,530,531],{},"June 20, 2023",[66,533,534],{},"Firebase deprecates sending through the legacy FCM HTTP and XMPP APIs, including upstream messages",[66,536,537],{},[88,538,540],{"href":96,"rel":539},[98],"Firebase (archived guide)",[42,542,543,547,552],{},[66,544,545],{},[17,546,71],{},[66,548,549],{},[17,550,551],{},"Shutdown of the legacy send APIs begins",[66,553,554],{},[88,555,540],{"href":96,"rel":556},[98],[42,558,559,562,565],{},[66,560,561],{},"September 2026",[66,563,564],{},"Firebase deprecates all InstanceId server APIs and the device group feature",[66,566,567],{},[88,568,570],{"href":222,"rel":569},[98],"Firebase FAQ",[42,572,573,576,579],{},[66,574,575],{},"January 1, 2027",[66,577,578],{},"New users can no longer start using the deprecated APIs",[66,580,581],{},[88,582,570],{"href":222,"rel":583},[98],[42,585,586,590,595],{},[66,587,588],{},[17,589,198],{},[66,591,592],{},[17,593,594],{},"Requests to the InstanceId server APIs and device group management start failing",[66,596,597],{},[88,598,570],{"href":222,"rel":599},[98],[14,601,602],{},"Firebase says there is no service downgrade before September 29, 2027, so the second change gives you roughly a year from the announcement. The first one is already done.",[251,604,606],{"id":605},"what-the-old-addresses-do-today","What the old addresses do today",[14,608,609],{},"Checked on October 18, 2026:",[611,612,613,626,640],"ul",{},[278,614,615,616,622,623,328],{},"A POST to ",[17,617,618],{},[88,619,620],{"href":620,"rel":621},"https:\u002F\u002Ffcm.googleapis.com\u002Ffcm\u002Fsend",[98],", the legacy send endpoint, returned ",[17,624,625],{},"404",[278,627,628,631,632,634,635,639],{},[17,629,630],{},"firebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fmigrate-v1",", the migration guide most tutorials link to, returned ",[17,633,625],{},". The ",[88,636,638],{"href":96,"rel":637},[98],"Wayback Machine copy from January 2026"," still has the full text.",[278,641,642,645],{},[17,643,644],{},"firebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fhttp-server-ref",", the legacy protocol reference, redirects to Firebase's server environment page.",[31,647,649],{"id":648},"moving-sends-to-http-v1","Moving sends to HTTP v1",[275,651,652,670,676,694,730,736,742],{},[278,653,654,657,658,661,662,665,666,669],{},[17,655,656],{},"Find the old code."," Search your server, Cloud Functions and any scripts for ",[80,659,660],{},"fcm.googleapis.com\u002Ffcm\u002Fsend",", an ",[80,663,664],{},"Authorization: key="," header, ",[80,667,668],{},"registration_ids",", or an XMPP connection to FCM. Also check third-party tools or plugins that send pushes for you: any that were set up with an FCM server key need updating or replacing.",[278,671,672,675],{},[17,673,674],{},"Use the Admin SDK if you can."," Firebase calls the Admin SDK the recommended method for sending from a server. It handles authorization and the new message format, and it can send the same message to a list of tokens for you.",[278,677,678,681,682,685,686,689,690,693],{},[17,679,680],{},"Or call HTTP v1 directly."," Send a POST to ",[80,683,684],{},"https:\u002F\u002Ffcm.googleapis.com\u002Fv1\u002Fprojects\u002FPROJECT_ID\u002Fmessages:send"," with an ",[80,687,688],{},"Authorization: Bearer \u003Caccess token>"," header. The token is a short-lived OAuth 2.0 access token from a service account, requested with the ",[80,691,692],{},"https:\u002F\u002Fwww.googleapis.com\u002Fauth\u002Ffirebase.messaging"," scope. Google's auth libraries can request and refresh it.",[278,695,696,699,700,703,704,707,708,711,712,715,716,350,719,722,723,726,727,729],{},[17,697,698],{},"Change the message shape."," HTTP v1 wraps everything in a ",[80,701,702],{},"message"," object with exactly one target, such as a ",[80,705,706],{},"token",", a ",[80,709,710],{},"topic"," or a ",[80,713,714],{},"condition",". Platform settings move into ",[80,717,718],{},"android",[80,720,721],{},"apns"," and ",[80,724,725],{},"webpush"," blocks. There's no ",[80,728,668],{}," list. To reach many devices, send one request per token, use a topic or condition, or use the Admin SDK's multi-token sending, which still makes one request per token behind the scenes.",[278,731,732,735],{},[17,733,734],{},"Enable the API."," If you get errors reaching the endpoint, check that \"Firebase Cloud Messaging API\" is enabled for the project in the Google Cloud console, as Firebase's guide says.",[278,737,738,741],{},[17,739,740],{},"Keep the service account key off devices."," It belongs on your server or in a secret manager, never in the mobile app or a public repository. If a key was ever committed to a repository, replace it.",[278,743,744,747],{},[17,745,746],{},"Test with real devices."," Send a test message to an Android phone and an iPhone (and a web client, if you use FCM on the web), with the app in the foreground, in the background and closed, before you remove the old code path. Once nothing uses them, delete or restrict the old server keys so they can't be leaked and reused.",[31,749,751],{"id":750},"before-september-29-2027","Before September 29, 2027",[14,753,754],{},"The second deprecation hits apps that used the older InstanceId server APIs or device groups, even if sending already moved to HTTP v1.",[36,756,757,770],{},[39,758,759],{},[42,760,761,764,767],{},[45,762,763],{},"If you use",[45,765,766],{},"It stops working",[45,768,769],{},"What to do instead",[61,771,772,790,816,830,850],{},[42,773,774,781,784],{},[66,775,776,777,780],{},"InstanceId info API (",[80,778,779],{},"iid.googleapis.com\u002Fiid\u002Finfo",") to check tokens",[66,782,783],{},"After September 29, 2027",[66,785,786,787,789],{},"To validate a token, send through HTTP v1 with ",[80,788,214],{}," set to true. For topic info, use the new topic subscription API",[42,791,792,805,807],{},[66,793,794,795,350,798,350,801,804],{},"InstanceId topic subscription APIs (",[80,796,797],{},"iid\u002Fv1\u002F...\u002Frel\u002Ftopics",[80,799,800],{},"batchAdd",[80,802,803],{},"batchRemove",")",[66,806,783],{},[66,808,809,810,815],{},"The new ",[88,811,814],{"href":812,"rel":813},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Freference\u002Ffcm\u002Ffcmtopics\u002Frest",[98],"FCM topic subscription API",", or a current Admin SDK",[42,817,818,825,827],{},[66,819,820,821,824],{},"InstanceId batch import (",[80,822,823],{},"iid\u002Fv1:batchImport",") to turn APNs tokens into FCM tokens",[66,826,783],{},[66,828,829],{},"Send through Apple's APNs directly, or add the FCM iOS SDK so the app registers itself",[42,831,832,839,841],{},[66,833,834,835,838],{},"Device group management (",[80,836,837],{},"fcm.googleapis.com\u002Ffcm\u002Fnotification"," and similar)",[66,840,783],{},[66,842,843,844,849],{},"Follow Firebase's ",[88,845,848],{"href":846,"rel":847},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fmigrate-off-device-groups",[98],"guide to migrating off device groups"," and send to individual tokens",[42,851,852,855,858],{},[66,853,854],{},"Sending to a device group key through HTTP v1",[66,856,857],{},"Group keys stop working after September 29, 2027",[66,859,860],{},"Send to each device's token instead",[14,862,863],{},"If you manage topic subscriptions with the Firebase Admin SDK, Firebase says earlier versions are affected and lists the versions to upgrade to: Node.js 14.5.0 or later, Python 7.7.0 or later, Java 9.11.0 or later, Go 4.22.0 or later, and .NET 3.7.0 or later.",[31,865,389],{"id":388},[14,867,868,869,871,872,876,877,328],{},"If pushes still don't arrive after the move, or you're not sure which parts of your backend touch the old APIs, the ",[88,870,396],{"href":395}," covers API, webhook and Cloud Function errors 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. For help with something else in a Firebase app, see ",[88,873,875],{"href":874},"\u002Fblog\u002Fhow-to-debug-a-flutter-firebase-bug-2026\u002F","how to debug a Flutter and Firebase bug",", or ",[88,878,401],{"href":400},{"title":404,"searchDepth":405,"depth":405,"links":880},[881,884,885,886],{"id":509,"depth":405,"text":510,"children":882},[883],{"id":605,"depth":411,"text":606},{"id":648,"depth":405,"text":649},{"id":750,"depth":405,"text":751},{"id":388,"depth":405,"text":389},"2026-10-18T21:00:00.000Z","Firebase shut down the legacy FCM send APIs from July 22, 2024, and in September 2026 deprecated the InstanceId server APIs and device groups, with a September 29, 2027 deadline. How to move push notifications to HTTP v1 and what to change before 2027.",[890,893,896,899,902,905],{"question":891,"answer":892},"Why did my Firebase push notifications stop working in 2024?","Most likely your server still sent through the legacy FCM API (fcm.googleapis.com\u002Ffcm\u002Fsend, with a server key). Firebase deprecated those APIs on June 20, 2023 and began shutting them down on July 22, 2024. Move your server to the HTTP v1 API or the Firebase Admin SDK.",{"question":894,"answer":895},"What replaced the FCM server key?","A short-lived OAuth 2.0 access token derived from a service account. The Firebase Admin SDK creates and refreshes it for you. If you call the HTTP v1 API directly, you request the token yourself and send it as a Bearer token.",{"question":897,"answer":898},"Is the FCM legacy API completely gone?","For sending, yes. On October 18, 2026, a POST to fcm.googleapis.com\u002Ffcm\u002Fsend returned 404. Some related legacy endpoints, such as the InstanceId server APIs and device group management, still work until September 29, 2027, and then start failing.",{"question":900,"answer":901},"What is changing on September 29, 2027?","Firebase is decommissioning all InstanceId server APIs (iid.googleapis.com, used for token info, topic subscriptions and batch import of APNs tokens) and the device group feature. After that date, requests to those APIs fail and device group tokens stop working with the HTTP v1 send API. New users can't start using them after January 1, 2027.",{"question":903,"answer":904},"Do I need to change my Flutter, Android or iOS app?","Usually not for the send migration, because the change is on your server. The exceptions: apps that sent upstream messages from the device, which were deprecated along with the legacy APIs; apps that relied on device groups; and iOS setups that used server-side batch import of APNs tokens, which the FCM iOS SDK replaces.",{"question":906,"answer":907},"Where is the official FCM migration guide now?","The old URL, firebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fmigrate-v1, returned 404 on October 18, 2026. The Wayback Machine has a copy from January 2026. The current Firebase pages for sending are the HTTP v1 send guide and the server environment page, both linked in the sources.",{"readingTimeStats":909},{"text":910,"minutes":911,"time":912,"words":913},"5 min read",4.56,273600,912,"\u002Fblog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026","fcm legacy api shutdown",[455,917,918],"how-to-debug-a-flutter-firebase-bug-2026","firebase-security-guide-2026",{"title":488,"description":888},[921,923,925,928,931,933,935],{"title":922,"url":96},"Firebase, \"Migrate from legacy FCM APIs to HTTP v1\" (Wayback Machine copy, January 8, 2026)",{"title":924,"url":222},"Firebase, Cloud Messaging FAQ and troubleshooting (FCM legacy API deprecations, September 2026)",{"title":926,"url":927},"Firebase, send messages with the HTTP v1 API","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fsend\u002Fv1-api",{"title":929,"url":930},"Firebase, FCM server environment","https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fcloud-messaging\u002Fserver-environment",{"title":932,"url":812},"Firebase, FCM topic subscription REST API",{"title":934,"url":846},"Firebase, migrate off device groups",{"title":936,"url":937},"Google, InstanceId server reference","https:\u002F\u002Fdevelopers.google.com\u002Finstance-id\u002Freference\u002Fserver","blog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026","fcm legacy api shutdown, fcm http v1 migration, fcm server key deprecated, fcm\u002Fsend 404, firebase push notifications stopped working, fcm device groups deprecated, instanceid api deprecated, iid.googleapis.com, fcm topic subscription api, firebase admin sdk messaging",[941,942,943,944,945],"Firebase deprecated sending through the legacy FCM HTTP and XMPP APIs on June 20, 2023, and began shutting them down on July 22, 2024. On October 18, 2026, the old fcm.googleapis.com\u002Ffcm\u002Fsend endpoint returned 404.","The replacement is the FCM HTTP v1 API, authorized with short-lived OAuth 2.0 access tokens from a service account instead of a server key. Firebase recommends the Admin SDK, which handles the tokens for you.","A second deadline is coming: in September 2026 Firebase deprecated all InstanceId server APIs and the device group feature. Requests to them start failing after September 29, 2027.","If you manage topic subscriptions with an older Firebase Admin SDK, you are affected by the 2027 change. Firebase lists the minimum versions to upgrade to, such as Node.js 14.5.0 and Python 7.7.0.","Firebase's old migration guide URL now returns 404, so many tutorials that link to it lead nowhere. This page collects the dates, the steps and the current Firebase pages in one place.","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffcm-legacy-api-shutdown-http-v1-migration-2026\u002F","A_ao7VryjLaWdcj-L_c1xjs6KP8d29Wvnc4d8yJV8dM",{"id":949,"title":950,"author":951,"body":953,"category":418,"createdAt":1674,"description":1675,"disclosure":421,"extension":422,"faq":1676,"howTo":421,"location":442,"meta":1695,"navigation":449,"ogImage":421,"path":1701,"primaryKeyword":1702,"readingTime":1703,"related":1704,"seo":1706,"sources":1707,"stem":1754,"tags":1755,"takeaways":1756,"updatedAt":1763,"url":1764,"__hash__":1765},"blog\u002Fblog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026.md","Deep Linking in 2026: What Replaced Firebase Dynamic Links and How to Set It Up",{"name":7,"social":952},{"twitter":9},{"type":11,"value":954,"toc":1663},[955,961,964,968,1008,1011,1015,1018,1039,1042,1059,1062,1066,1075,1078,1082,1211,1214,1218,1253,1256,1260,1263,1293,1394,1419,1495,1498,1572,1575,1579,1606,1609,1635,1638,1640,1643,1659],[14,956,957,960],{},[17,958,959],{},"A deep link is a link that opens a specific screen inside a mobile app, not just the app's front door. Firebase Dynamic Links, the free Google service many apps used for this, shut down on August 25, 2025."," In 2026 you have two real choices. Use Universal Links and Android App Links on your own domain for free, or pay a provider such as Branch, AppsFlyer, Adjust or Airbridge if you need links that survive an app install.",[14,962,963],{},"This guide replaces the older deep linking explainers and vendor docs that no longer load. Every date and price below comes from the vendor's own page, checked on October 17, 2026.",[31,965,967],{"id":966},"what-deep-linking-means-in-plain-words","What deep linking means, in plain words",[611,969,970,976,986,996,1002],{},[278,971,972,975],{},[17,973,974],{},"Deep link."," A link that goes to a place inside an app, such as a product, an invoice or an invite. A normal link opens the app's home screen at best.",[278,977,978,981,982,985],{},[17,979,980],{},"Universal Links (iOS)."," Apple's version. You tap a normal https link, and iOS opens your app if it is installed. If not, the link opens in the browser. Apple checks a file on your website, called ",[80,983,984],{},"apple-app-site-association",", to confirm the link belongs to your app.",[278,987,988,991,992,995],{},[17,989,990],{},"Android App Links."," Google's version. Same idea. Android checks a file called ",[80,993,994],{},"assetlinks.json"," on your website.",[278,997,998,1001],{},[17,999,1000],{},"Deferred deep link."," A link that works even when the app is not installed yet. The user taps, installs the app from the store, and lands on the right screen on first open. This is what Dynamic Links did well, and it is the part plain Universal Links and App Links do not do.",[278,1003,1004,1007],{},[17,1005,1006],{},"Click analytics."," Counts of who clicked which link. Dynamic Links had some. Google's migration guide offers no replacement for it.",[14,1009,1010],{},"Marketers mostly care about the last two. Developers mostly care about the first three.",[31,1012,1014],{"id":1013},"what-happened-to-firebase-dynamic-links","What happened to Firebase Dynamic Links",[14,1016,1017],{},"Google's own FAQ says Dynamic Links shut down on August 25, 2025. This is what that means for old links:",[611,1019,1020,1023,1026,1033,1036],{},[278,1021,1022],{},"Every clicked link returns an HTTP 404 to the user.",[278,1024,1025],{},"Short link creation and link stats API calls return 400 or 403 errors.",[278,1027,1028,1029,1032],{},"Existing ",[80,1030,1031],{},".page.link"," domains cannot be kept or transferred. Domain and link data is marked for deletion on the shutdown date.",[278,1034,1035],{},"The SDKs will not crash your app by themselves, but your code has to handle the new responses. For example, on iOS, short link creation now returns a 403, and first-open attribution returns empty data.",[278,1037,1038],{},"Email link sign-in, password reset and email verification on mobile needed updated SDKs. Google has separate guides for iOS and Android.",[14,1040,1041],{},"Google's own advice, in its FAQ:",[275,1043,1044,1047,1050,1053],{},[278,1045,1046],{},"If you need full feature parity, use a third-party provider. The FAQ names Adjust, Airbridge, AppsFlyer, Bitly, Branch, Kochava and Singular, and says Google has not vetted them.",[278,1048,1049],{},"If you only need to open an installed app, use Universal Links and App Links. The official migration guide covers this path.",[278,1051,1052],{},"If you no longer need the links, review them, delete the URL prefixes and remove the SDK.",[278,1054,1055,1056,328],{},"Export your link metadata, and if you keep a custom domain, update your rewrite rules in ",[80,1057,1058],{},"firebase.json",[14,1060,1061],{},"The migration guide is honest about the gap. Universal Links and App Links do not send users to the app store, and do not carry the journey through a first install. For iOS it recommends Smart App Banners as the closest substitute.",[251,1063,1065],{"id":1064},"firebase-invites-went-first-in-2020","Firebase Invites went first, in 2020",[14,1067,1068,1069,1074],{},"Firebase Invites was the layer on top of Dynamic Links that let users send an app invite by SMS or email. Firebase's ",[88,1070,1073],{"href":1071,"rel":1072},"https:\u002F\u002Fweb.archive.org\u002Fweb\u002F20201201222821\u002Fhttps:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Finvites\u002Fdeprecation",[98],"deprecation notice"," was online by March 31, 2019, the earliest Wayback Machine capture, and said support would be discontinued on January 24, 2020. Its advice was to keep Dynamic Links and build your own sharing screen. That path closed too when Dynamic Links shut down.",[14,1076,1077],{},"On October 18, 2026, firebase.google.com\u002Fdocs\u002Finvites and its sub-pages returned a 404. If an app still has an \"invite a friend\" feature from that era, the fix today is the same as for Dynamic Links: share a Universal Link or App Link through the system share sheet, and add a provider only if you need to know which invite led to an install.",[31,1079,1081],{"id":1080},"what-to-use-now","What to use now",[36,1083,1084,1100],{},[39,1085,1086],{},[42,1087,1088,1091,1094,1097],{},[45,1089,1090],{},"Option",[45,1092,1093],{},"Deferred deep linking",[45,1095,1096],{},"Click analytics",[45,1098,1099],{},"Price (checked October 17, 2026)",[61,1101,1102,1117,1137,1157,1177,1196],{},[42,1103,1104,1109,1112,1114],{},[66,1105,1106],{},[17,1107,1108],{},"Universal Links + App Links on your own domain",[66,1110,1111],{},"No",[66,1113,1111],{},[66,1115,1116],{},"Free. You pay for your domain and hosting.",[42,1118,1119,1124,1127,1129],{},[66,1120,1121],{},[17,1122,1123],{},"Branch",[66,1125,1126],{},"Yes",[66,1128,1126],{},[66,1130,1131,1132],{},"Basics plan: free trial, no price shown. Essentials and Enterprise: \"Request a demo.\" See ",[88,1133,1136],{"href":1134,"rel":1135},"https:\u002F\u002Fwww.branch.io\u002Fpricing\u002F",[98],"branch.io\u002Fpricing",[42,1138,1139,1144,1147,1149],{},[66,1140,1141],{},[17,1142,1143],{},"AppsFlyer (OneLink)",[66,1145,1146],{},"Yes, from the Standard plan (Zero is free but has no deferred linking)",[66,1148,1126],{},[66,1150,1151,1152],{},"Deep Linking plans: Zero is labelled \"Free.\" Standard, Advanced and Premium show \"Custom pricing\" with \"Request a demo.\" See ",[88,1153,1156],{"href":1154,"rel":1155},"https:\u002F\u002Fwww.appsflyer.com\u002Fpricing\u002Fdeep-linking",[98],"appsflyer.com\u002Fpricing\u002Fdeep-linking",[42,1158,1159,1164,1166,1168],{},[66,1160,1161],{},[17,1162,1163],{},"Adjust",[66,1165,1126],{},[66,1167,1126],{},[66,1169,1170,1171,1176],{},"See ",[88,1172,1175],{"href":1173,"rel":1174},"https:\u002F\u002Fwww.adjust.com\u002Fpricing\u002F",[98],"adjust.com\u002Fpricing",". Its pricing page would not load for me on October 17, so I am not quoting a number.",[42,1178,1179,1184,1186,1188],{},[66,1180,1181],{},[17,1182,1183],{},"Airbridge",[66,1185,1126],{},[66,1187,1126],{},[66,1189,1190,1191],{},"Core plan: $40+ a month after a 30-day free trial, deep linking included. Growth plan: custom. See ",[88,1192,1195],{"href":1193,"rel":1194},"https:\u002F\u002Fwww.airbridge.io\u002Fpricing",[98],"airbridge.io\u002Fpricing",[42,1197,1198,1203,1206,1208],{},[66,1199,1200],{},[17,1201,1202],{},"Bitly, Kochava, Singular",[66,1204,1205],{},"Check each vendor",[66,1207,1205],{},[66,1209,1210],{},"Named in Google's FAQ. Prices not checked here, so see each vendor's pricing page.",[14,1212,1213],{},"Two cautions on that table. First, \"deferred\" and \"analytics\" here are what these vendors sell in general. Test the exact features on the plan you are quoted. Second, several of these tools are attribution platforms first and link tools second. If you only need links, that can be a lot of product to buy.",[31,1215,1217],{"id":1216},"how-to-choose","How to choose",[275,1219,1220,1226,1232,1238,1244],{},[278,1221,1222,1225],{},[17,1223,1224],{},"Your users already have the app, and links come from emails, your website or in-app shares."," Use plain Universal Links and App Links. It is free, it is the platform's own mechanism, and no vendor can shut it down.",[278,1227,1228,1231],{},[17,1229,1230],{},"You run paid ads that send new users to the app store."," You need deferred deep linking and attribution. Pick a provider, and ask for a quote that matches your install volume.",[278,1233,1234,1237],{},[17,1235,1236],{},"You are a small team that wants links and little else."," Look at the lowest published tier first (Airbridge Core or AppsFlyer Zero; Zero covers basic routing only), and read what the free or entry plan actually excludes before you commit.",[278,1239,1240,1243],{},[17,1241,1242],{},"You want first-open routing without a vendor."," Combine Universal Links, a Smart App Banner on iOS, and a small server route that remembers the intended screen. It takes some build time, but you own it.",[278,1245,1246,1249,1250,1252],{},[17,1247,1248],{},"You have old Dynamic Links printed or published."," Links on a ",[80,1251,1031],{}," domain are gone for good, because Google will not let anyone keep those domains. If your links used your own custom domain, point that domain at your website and redirect the old paths to the right pages. Either way, publish new links on your own domain.",[14,1254,1255],{},"If you are unsure, start with option 1. You can add a provider later without changing your domain files.",[31,1257,1259],{"id":1258},"set-up-universal-links-and-app-links-on-your-own-domain","Set up Universal Links and App Links on your own domain",[14,1261,1262],{},"Use a domain you control, and use the same domain in every step. Apple and Google both want the files served over HTTPS with no redirects.",[275,1264,1265,1279],{},[278,1266,1267,1270,1271,1274,1275,1278],{},[17,1268,1269],{},"Pick the links."," Decide which paths open the app, for example ",[80,1272,1273],{},"\u002Finvite\u002F*"," or ",[80,1276,1277],{},"\u002Finvoice\u002F*",". Keep the list short.",[278,1280,1281,1284,1285,1288,1289,1292],{},[17,1282,1283],{},"Create the iOS file."," Host it at ",[80,1286,1287],{},"https:\u002F\u002Fyourdomain.com\u002F.well-known\u002Fapple-app-site-association",". The name has no ",[80,1290,1291],{},".json"," extension. Apple's docs say to host it over HTTPS with a valid certificate and no redirects. A minimal version looks like this:",[1294,1295,1299],"pre",{"className":1296,"code":1297,"language":1298,"meta":404,"style":404},"language-json shiki shiki-themes github-light github-dark","{\n  \"applinks\": {\n    \"details\": [\n      {\n        \"appIDs\": [\"TEAMID.com.example.app\"],\n        \"components\": [{ \"\u002F\": \"\u002Finvite\u002F*\" }]\n      }\n    ]\n  }\n}\n","json",[80,1300,1301,1310,1319,1327,1333,1349,1370,1376,1382,1388],{"__ignoreMap":404},[1302,1303,1306],"span",{"class":1304,"line":1305},"line",1,[1302,1307,1309],{"class":1308},"sVt8B","{\n",[1302,1311,1312,1316],{"class":1304,"line":405},[1302,1313,1315],{"class":1314},"sj4cs","  \"applinks\"",[1302,1317,1318],{"class":1308},": {\n",[1302,1320,1321,1324],{"class":1304,"line":411},[1302,1322,1323],{"class":1314},"    \"details\"",[1302,1325,1326],{"class":1308},": [\n",[1302,1328,1330],{"class":1304,"line":1329},4,[1302,1331,1332],{"class":1308},"      {\n",[1302,1334,1336,1339,1342,1346],{"class":1304,"line":1335},5,[1302,1337,1338],{"class":1314},"        \"appIDs\"",[1302,1340,1341],{"class":1308},": [",[1302,1343,1345],{"class":1344},"sZZnC","\"TEAMID.com.example.app\"",[1302,1347,1348],{"class":1308},"],\n",[1302,1350,1352,1355,1358,1361,1364,1367],{"class":1304,"line":1351},6,[1302,1353,1354],{"class":1314},"        \"components\"",[1302,1356,1357],{"class":1308},": [{ ",[1302,1359,1360],{"class":1314},"\"\u002F\"",[1302,1362,1363],{"class":1308},": ",[1302,1365,1366],{"class":1344},"\"\u002Finvite\u002F*\"",[1302,1368,1369],{"class":1308}," }]\n",[1302,1371,1373],{"class":1304,"line":1372},7,[1302,1374,1375],{"class":1308},"      }\n",[1302,1377,1379],{"class":1304,"line":1378},8,[1302,1380,1381],{"class":1308},"    ]\n",[1302,1383,1385],{"class":1304,"line":1384},9,[1302,1386,1387],{"class":1308},"  }\n",[1302,1389,1391],{"class":1304,"line":1390},10,[1302,1392,1393],{"class":1308},"}\n",[275,1395,1396,1406],{"start":411},[278,1397,1398,1401,1402,1405],{},[17,1399,1400],{},"Add the iOS entitlement."," In Xcode, open Signing & Capabilities, add Associated Domains, and add ",[80,1403,1404],{},"applinks:yourdomain.com",". Use the bare domain, with no path and no trailing slash. Personal development teams cannot use this capability (per Flutter's setup guide).",[278,1407,1408,1284,1411,1414,1415,1418],{},[17,1409,1410],{},"Create the Android file.",[80,1412,1413],{},"https:\u002F\u002Fyourdomain.com\u002F.well-known\u002Fassetlinks.json",", with content type ",[80,1416,1417],{},"application\u002Fjson"," and no redirects:",[1294,1420,1422],{"className":1296,"code":1421,"language":1298,"meta":404,"style":404},"[{\n  \"relation\": [\"delegate_permission\u002Fcommon.handle_all_urls\"],\n  \"target\": {\n    \"namespace\": \"android_app\",\n    \"package_name\": \"com.example.app\",\n    \"sha256_cert_fingerprints\": [\"AA:BB:...:FF\"]\n  }\n}]\n",[80,1423,1424,1429,1441,1448,1461,1473,1486,1490],{"__ignoreMap":404},[1302,1425,1426],{"class":1304,"line":1305},[1302,1427,1428],{"class":1308},"[{\n",[1302,1430,1431,1434,1436,1439],{"class":1304,"line":405},[1302,1432,1433],{"class":1314},"  \"relation\"",[1302,1435,1341],{"class":1308},[1302,1437,1438],{"class":1344},"\"delegate_permission\u002Fcommon.handle_all_urls\"",[1302,1440,1348],{"class":1308},[1302,1442,1443,1446],{"class":1304,"line":411},[1302,1444,1445],{"class":1314},"  \"target\"",[1302,1447,1318],{"class":1308},[1302,1449,1450,1453,1455,1458],{"class":1304,"line":1329},[1302,1451,1452],{"class":1314},"    \"namespace\"",[1302,1454,1363],{"class":1308},[1302,1456,1457],{"class":1344},"\"android_app\"",[1302,1459,1460],{"class":1308},",\n",[1302,1462,1463,1466,1468,1471],{"class":1304,"line":1335},[1302,1464,1465],{"class":1314},"    \"package_name\"",[1302,1467,1363],{"class":1308},[1302,1469,1470],{"class":1344},"\"com.example.app\"",[1302,1472,1460],{"class":1308},[1302,1474,1475,1478,1480,1483],{"class":1304,"line":1351},[1302,1476,1477],{"class":1314},"    \"sha256_cert_fingerprints\"",[1302,1479,1341],{"class":1308},[1302,1481,1482],{"class":1344},"\"AA:BB:...:FF\"",[1302,1484,1485],{"class":1308},"]\n",[1302,1487,1488],{"class":1304,"line":1372},[1302,1489,1387],{"class":1308},[1302,1491,1492],{"class":1304,"line":1378},[1302,1493,1494],{"class":1308},"}]\n",[14,1496,1497],{},"If you use Google Play App Signing, copy the fingerprint from the Play Console (Release, Setup, App signing). The one from your local keystore will usually not match what is on users' phones.",[275,1499,1500,1532,1538],{"start":1335},[278,1501,1502,1505,1506,1509,1510,1513,1514,1517,1518,1521,1522,722,1525,1528,1529,328],{},[17,1503,1504],{},"Add the Android intent filter."," In ",[80,1507,1508],{},"AndroidManifest.xml",", add an ",[80,1511,1512],{},"intent-filter"," with ",[80,1515,1516],{},"android:autoVerify=\"true\"",", the ",[80,1519,1520],{},"VIEW"," action, the ",[80,1523,1524],{},"DEFAULT",[80,1526,1527],{},"BROWSABLE"," categories, and ",[80,1530,1531],{},"\u003Cdata android:scheme=\"https\" android:host=\"yourdomain.com\" \u002F>",[278,1533,1534,1537],{},[17,1535,1536],{},"Handle the link in your app."," Read the incoming URL and route to the right screen. Do this for both a cold start and an app that is already running.",[278,1539,1540,1543],{},[17,1541,1542],{},"Test before you ship.",[611,1544,1545,1552,1569],{},[278,1546,1547,1548,1551],{},"iOS: Apple fetches your file through its own CDN. Per Apple's docs, the CDN asks for your file within 24 hours, and devices re-check about once a week. You can see what Apple has cached at ",[80,1549,1550],{},"https:\u002F\u002Fapp-site-association.cdn-apple.com\u002Fa\u002Fv1\u002Fyourdomain.com",". For a private dev server, Apple's alternate mode bypasses the CDN. Then tap a link from the Notes app on a real device.",[278,1553,1554,1555,1558,1559,1562,1563,1568],{},"Android: run ",[80,1556,1557],{},"adb shell pm get-app-links com.example.app"," and look for ",[80,1560,1561],{},"verified"," next to your domain. Google's ",[88,1564,1567],{"href":1565,"rel":1566},"https:\u002F\u002Fdevelopers.google.com\u002Fdigital-asset-links\u002Ftools\u002Fgenerator",[98],"Statement List Generator and Tester"," can generate and check the file.",[278,1570,1571],{},"I know of no Apple-run web validator for the apple-app-site-association file today, so on iOS rely on the CDN URL above and a real device.",[14,1573,1574],{},"The usual failures are a redirect in front of the file (including www to non-www), the wrong signing fingerprint, a Team ID typo, and testing before Apple's CDN has caught up.",[31,1576,1578],{"id":1577},"flutter-specifics","Flutter specifics",[14,1580,1581,1582,722,1587,1592,1593,1596,1597,722,1600,1603,1604,328],{},"Flutter has official guides for both platforms: ",[88,1583,1586],{"href":1584,"rel":1585},"https:\u002F\u002Fdocs.flutter.dev\u002Fcookbook\u002Fnavigation\u002Fset-up-universal-links",[98],"set up universal links",[88,1588,1591],{"href":1589,"rel":1590},"https:\u002F\u002Fdocs.flutter.dev\u002Fcookbook\u002Fnavigation\u002Fset-up-app-links",[98],"set up app links",". Per those pages, Flutter 3.27 and later turn deep linking on by default. Older versions need ",[80,1594,1595],{},"FlutterDeepLinkingEnabled"," set to YES in ",[80,1598,1599],{},"Info.plist",[80,1601,1602],{},"flutter_deeplinking_enabled"," set to true in ",[80,1605,1508],{},[14,1607,1608],{},"Two ways to receive links:",[611,1610,1611,1621],{},[278,1612,1613,1616,1617,1620],{},[17,1614,1615],{},"go_router."," Flutter's built-in handling feeds incoming links to the ",[80,1618,1619],{},"Router",". go_router (version 18.1.0 on pub.dev today) is a declarative router built on that system and lists deep linking as a feature. Define your paths as routes, and an incoming link lands on the matching screen.",[278,1622,1623,1626,1627,1630,1631,1634],{},[17,1624,1625],{},"app_links."," The ",[80,1628,1629],{},"app_links"," package (7.2.2 today) handles Android App Links, iOS Universal Links and custom schemes. You subscribe to ",[80,1632,1633],{},"AppLinks().uriLinkStream",", which delivers both the first link and later ones. Per Flutter's docs, if you use a plugin like this, set the deep linking flag to false so Flutter's own handler does not conflict.",[14,1636,1637],{},"Flutter DevTools also has a Deep Links validator. It checks website configuration and manifest files, and works for Android and iOS from Flutter 3.27.",[31,1639,389],{"id":388},[14,1641,1642],{},"App369 is Simon Dziak's studio. He builds and runs Workspace369, a production Flutter and Firebase SaaS.",[611,1644,1645,1651],{},[278,1646,1647,1648,1650],{},"Links open the wrong screen, or the app never opens from a link: the ",[88,1649,396],{"href":395}," diagnoses one issue for $450 and fixes it for $1,200, both fixed price (the $450 is credited toward the fix).",[278,1652,1653,1654,1658],{},"Connecting a link provider, your backend and a CRM or Stripe: ",[88,1655,1657],{"href":1656},"\u002Ffixed-price\u002Fapi-integration\u002F","API Integration",", $1,200 fixed price, 5 business days.",[1660,1661,1662],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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":404,"searchDepth":405,"depth":405,"links":1664},[1665,1666,1669,1670,1671,1672,1673],{"id":966,"depth":405,"text":967},{"id":1013,"depth":405,"text":1014,"children":1667},[1668],{"id":1064,"depth":411,"text":1065},{"id":1080,"depth":405,"text":1081},{"id":1216,"depth":405,"text":1217},{"id":1258,"depth":405,"text":1259},{"id":1577,"depth":405,"text":1578},{"id":388,"depth":405,"text":389},"2026-10-17T12:00:00.000Z","What deep linking is, what happened when Firebase Invites (2020) and Firebase Dynamic Links (August 25, 2025) shut down, and how to set up Universal Links and Android App Links in 2026. Vendor options and prices checked October 17, 2026.",[1677,1680,1683,1686,1689,1692],{"question":1678,"answer":1679},"When did Firebase Dynamic Links shut down?","On August 25, 2025. Google says all clicked links return an HTTP 404, short link and link stats API calls return 400 or 403 errors, and existing .page.link domains cannot be kept or transferred.",{"question":1681,"answer":1682},"What replaced Firebase Dynamic Links?","Nothing from Google replaced it one for one. Google tells developers to use Universal Links and Android App Links for links that open an installed app, and a third-party deep linking provider for full feature parity. Google names Adjust, Airbridge, AppsFlyer, Bitly, Branch, Kochava and Singular, and says it has not vetted them.",{"question":1684,"answer":1685},"What happened to Firebase Invites?","Firebase deprecated Invites and discontinued support on January 24, 2020. Its replacement was Dynamic Links with your own sharing screen, and Dynamic Links shut down on August 25, 2025. Today the firebase.google.com\u002Fdocs\u002Finvites pages return a 404. For app invites now, share a Universal Link or App Link through the system share sheet, or use a deep linking provider if you need install attribution.",{"question":1687,"answer":1688},"What is a deferred deep link?","A link that still works when the app is not installed yet. The user taps, goes to the app store, installs the app, and lands on the right screen on first open. Universal Links and App Links cannot do this on their own. You need a provider or your own server logic.",{"question":1690,"answer":1691},"Do I need a paid service for deep links?","Not if your users already have the app. Universal Links and App Links cost nothing beyond a domain you own. You need a provider only for deferred deep linking, click analytics, or campaign attribution.",{"question":1693,"answer":1694},"How do I test Universal Links and App Links?","On iOS, check the file through Apple's CDN and tap a link from the Notes app. On Android, use adb pm get-app-links to see whether your domain shows as verified, and Google's Statement List Generator and Tester to check assetlinks.json. For Flutter apps, DevTools has a Deep Links validator.",{"readingTimeStats":1696},{"text":1697,"minutes":1698,"time":1699,"words":1700},"9 min read",8.36,501600,1672,"\u002Fblog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026","firebase dynamic links alternative","9 min",[1705,918,917],"mobile-app-analytics-tracking-guide-2026",{"title":950,"description":1675},[1708,1711,1713,1716,1719,1722,1725,1728,1730,1733,1735,1737,1740,1743,1746,1748,1750,1752],{"title":1709,"url":1710},"Firebase Dynamic Links FAQ (shutdown date, link behaviour, recommended alternatives)","https:\u002F\u002Ffirebase.google.com\u002Fsupport\u002Fdynamic-links-faq",{"title":1712,"url":1071},"Firebase, \"Migrating from Firebase Invites to Dynamic Links with Custom Sharing\" (Wayback Machine copy, December 2020)",{"title":1714,"url":1715},"Firebase, Migrate to App Links and Universal Links (official migration guide)","https:\u002F\u002Ffirebase.google.com\u002Fsupport\u002Fguides\u002Fapp-links-universal-links",{"title":1717,"url":1718},"Apple, Supporting associated domains","https:\u002F\u002Fdeveloper.apple.com\u002Fdocumentation\u002Fxcode\u002Fsupporting-associated-domains",{"title":1720,"url":1721},"Apple CDN copy of an apple-app-site-association file (example: www.apple.com)","https:\u002F\u002Fapp-site-association.cdn-apple.com\u002Fa\u002Fv1\u002Fwww.apple.com",{"title":1723,"url":1724},"Android, Verify Android App Links","https:\u002F\u002Fdeveloper.android.com\u002Ftraining\u002Fapp-links\u002Fverify-android-applinks",{"title":1726,"url":1727},"Android, Configure website associations (assetlinks.json requirements)","https:\u002F\u002Fdeveloper.android.com\u002Ftraining\u002Fapp-links\u002Fconfigure-assetlinks",{"title":1729,"url":1565},"Google, Statement List Generator and Tester",{"title":1731,"url":1732},"Flutter, Deep linking","https:\u002F\u002Fdocs.flutter.dev\u002Fui\u002Fnavigation\u002Fdeep-linking",{"title":1734,"url":1584},"Flutter, Set up universal links (iOS)",{"title":1736,"url":1589},"Flutter, Set up app links (Android)",{"title":1738,"url":1739},"Flutter DevTools, Validate deep links","https:\u002F\u002Fdocs.flutter.dev\u002Ftools\u002Fdevtools\u002Fdeep-links",{"title":1741,"url":1742},"app_links package on pub.dev","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fapp_links",{"title":1744,"url":1745},"go_router package on pub.dev","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fgo_router",{"title":1747,"url":1134},"Branch pricing",{"title":1749,"url":1154},"AppsFlyer deep linking pricing",{"title":1751,"url":1173},"Adjust pricing",{"title":1753,"url":1193},"Airbridge pricing","blog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026","firebase dynamic links alternative, firebase invites alternative, firebase invites deprecated, deep linking, deferred deep linking, universal links, android app links, apple-app-site-association, assetlinks.json, branch alternatives, appsflyer onelink, flutter deep linking, mobile deep linking",[1757,1758,1759,1760,1761,1762],"Firebase Dynamic Links shut down on August 25, 2025. Clicked links now return an HTTP 404, and Google says the .page.link domains cannot be kept or transferred.","Firebase Invites, which shared Dynamic Links by SMS or email, was discontinued first: Firebase stopped supporting it on January 24, 2020 and pointed developers to Dynamic Links, which have now shut down too.","Google names two routes. Use Universal Links and Android App Links if you only need links to open an installed app. Use a third-party provider if you need full feature parity.","Universal Links and App Links are free and live on your own domain. They do not do deferred deep linking, and they do not give you click analytics.","Two files make it work: \u002F.well-known\u002Fapple-app-site-association on iOS and \u002F.well-known\u002Fassetlinks.json on Android. Serve both over HTTPS with no redirects.","Pricing as of October 17, 2026: Airbridge Core is $40+ a month, AppsFlyer has a free Zero plan, Branch and the paid AppsFlyer plans are sales-led, and Adjust lists no price I could read.","2026-10-18T03:00:00.000Z","https:\u002F\u002Fapp369.com\u002Fblog\u002Ffirebase-dynamic-links-shutdown-deep-linking-2026\u002F","JEEsVmFihriiUlUKa5kE2kyn59Dh8wynAZFQueah2UU",{"id":1767,"title":1768,"author":1769,"body":1771,"category":418,"createdAt":2241,"description":2242,"disclosure":421,"extension":422,"faq":421,"howTo":421,"location":442,"meta":2243,"navigation":449,"ogImage":421,"path":2249,"primaryKeyword":421,"readingTime":2250,"related":421,"seo":2251,"sources":421,"stem":2252,"tags":2253,"takeaways":421,"updatedAt":2254,"url":2255,"__hash__":2256},"blog\u002Fblog\u002Fhow-to-cut-your-firebase-bill-2026.md","How to Cut Your Firebase Bill: A Line-by-Line Cost Audit (2026)",{"name":7,"social":1770},{"twitter":9},{"type":11,"value":1772,"toc":2222},[1773,1779,1787,1791,1800,1826,1830,1833,1868,1871,1875,1882,1937,1943,1950,1954,1978,1982,1985,2025,2029,2032,2043,2046,2050,2053,2073,2077,2080,2084,2087,2161,2164,2168,2180,2184,2188,2191,2195,2198,2202,2205,2209,2212,2216,2219],[14,1774,1775,1778],{},[17,1776,1777],{},"Most Firebase bills that keep creeping up have a few specific causes, and you can find them in an afternoon."," Measure what each service actually does, price it at Google's list prices, then rank every possible saving by dollars a month and by the risk your users would notice. Guessing (\"let's turn off min instances everywhere\") usually trades a small saving for slower screens.",[14,1780,1781,1782,1786],{},"This is the method App369 uses for its ",[88,1783,1785],{"href":1784},"\u002Ffixed-price\u002F#firebase-cost-audit","fixed-price Firebase Cost-Cut Audit",". It is also how Simon audits the production Firebase project behind his own SaaS, Workspace369, which runs about 980 Cloud Run services. On that project, the audit found that roughly 42% of steady-state spend was recoverable. It was a small bill, and not every finding was applied, but the pattern is common.",[31,1788,1790],{"id":1789},"why-firebase-bills-grow-quietly","Why Firebase bills grow quietly",[14,1792,1793,1794,1799],{},"Firebase's pay-as-you-go ",[88,1795,1798],{"href":1796,"rel":1797},"https:\u002F\u002Ffirebase.google.com\u002Fpricing",[98],"Blaze plan"," bills each product separately, so there is rarely one obvious line item. The usual sources are:",[611,1801,1802,1808,1814,1820],{},[278,1803,1804,1807],{},[17,1805,1806],{},"2nd gen Cloud Functions run on Cloud Run."," Every function is its own Cloud Run service with its own memory, CPU, concurrency and minimum-instance settings. A project with 100 functions has 100 sets of settings that nobody reviews after launch.",[278,1809,1810,1813],{},[17,1811,1812],{},"Minimum instances bill while idle."," Keeping an instance warm removes cold starts, but you pay for it around the clock, whether or not anyone calls the function.",[278,1815,1816,1819],{},[17,1817,1818],{},"Firestore bills per document read."," A screen that listens to a whole collection, or a scheduled job that scans one every few minutes, multiplies reads with no visible symptom.",[278,1821,1822,1825],{},[17,1823,1824],{},"Background work has no user to complain."," Retry loops, triggers that fire other triggers, and verbose logging run at full speed until the invoice arrives.",[31,1827,1829],{"id":1828},"step-1-measure-before-you-cut","Step 1: Measure before you cut",[14,1831,1832],{},"Start from data, not settings.",[275,1834,1835,1847,1857],{},[278,1836,1837,1840,1841,1846],{},[17,1838,1839],{},"Billing export."," If ",[88,1842,1845],{"href":1843,"rel":1844},"https:\u002F\u002Fcloud.google.com\u002Fbilling\u002Fdocs\u002Fhow-to\u002Fexport-data-bigquery",[98],"Cloud Billing export to BigQuery"," is on, you have actual spend by service and SKU. If it isn't, turn it on now; it only collects data from the day you enable it.",[278,1848,1849,1852,1853,1856],{},[17,1850,1851],{},"Usage from Cloud Monitoring."," For each Cloud Run service, pull 7 and 30 days of request count and billable instance time (",[80,1854,1855],{},"run.googleapis.com\u002Fcontainer\u002Fbillable_instance_time","). For Firestore, pull document reads, writes and deletes.",[278,1858,1859,1626,1862,1867],{},[17,1860,1861],{},"List prices.",[88,1863,1866],{"href":1864,"rel":1865},"https:\u002F\u002Fcloud.google.com\u002Fbilling\u002Fdocs\u002Fhow-to\u002Fget-pricing-information-api",[98],"Cloud Billing Catalog API"," returns the current price of every SKU in your region, so each estimate is priced from Google's own numbers rather than a blog post.",[14,1869,1870],{},"Multiply usage by price, per service, and you have an estimated monthly bill by service. Sort it. In most projects a handful of services account for most of the money.",[31,1872,1874],{"id":1873},"step-2-always-on-minimum-instances","Step 2: Always-on minimum instances",[14,1876,1877,1878,1881],{},"List every service with ",[80,1879,1880],{},"minInstances"," above zero:",[1294,1883,1887],{"className":1884,"code":1885,"language":1886,"meta":404,"style":404},"language-bash shiki shiki-themes github-light github-dark","gcloud run services list --format=json \\\n| jq -r '.[] | [.metadata.name, (.spec.template.metadata.annotations[\"autoscaling.knative.dev\u002FminScale\"] \u002F\u002F \"0\")] | @tsv' \\\n| awk '$2 > 0'\n","bash",[80,1888,1889,1910,1927],{"__ignoreMap":404},[1302,1890,1891,1895,1898,1901,1904,1907],{"class":1304,"line":1305},[1302,1892,1894],{"class":1893},"sScJk","gcloud",[1302,1896,1897],{"class":1344}," run",[1302,1899,1900],{"class":1344}," services",[1302,1902,1903],{"class":1344}," list",[1302,1905,1906],{"class":1314}," --format=json",[1302,1908,1909],{"class":1314}," \\\n",[1302,1911,1912,1916,1919,1922,1925],{"class":1304,"line":405},[1302,1913,1915],{"class":1914},"szBVR","|",[1302,1917,1918],{"class":1893}," jq",[1302,1920,1921],{"class":1314}," -r",[1302,1923,1924],{"class":1344}," '.[] | [.metadata.name, (.spec.template.metadata.annotations[\"autoscaling.knative.dev\u002FminScale\"] \u002F\u002F \"0\")] | @tsv'",[1302,1926,1909],{"class":1314},[1302,1928,1929,1931,1934],{"class":1304,"line":411},[1302,1930,1915],{"class":1914},[1302,1932,1933],{"class":1893}," awk",[1302,1935,1936],{"class":1344}," '$2 > 0'\n",[14,1938,1939,1940,1942],{},"For each one, ask whether a user waits on it. A login or checkout function may deserve a warm instance. A nightly report or a webhook that Stripe retries anyway usually doesn't. In code, the setting lives on the function (",[80,1941,1880],{}," in the Firebase Functions v2 options), so change it there, not only in the console, or the next deploy puts it back.",[14,1944,1945,1946,328],{},"To see what your current settings cost while idle, use the free ",[88,1947,1949],{"href":1948},"\u002Ftools\u002Fmin-instances-cost-calculator\u002F","min instances cost calculator",[31,1951,1953],{"id":1952},"step-3-memory-cpu-and-concurrency","Step 3: Memory, CPU and concurrency",[611,1955,1956,1962,1972],{},[278,1957,1958,1961],{},[17,1959,1960],{},"Memory."," Functions are often deployed at 1 GiB or more \"to be safe\". Compare the configured memory with the memory utilization metric and size down where the peak is far below the limit.",[278,1963,1964,1967,1968,1971],{},[17,1965,1966],{},"Concurrency."," 2nd gen functions can serve many requests per instance (80 by default with a full CPU); 1st gen functions serve one. A function forced to ",[80,1969,1970],{},"concurrency: 1"," scales out an instance per request.",[278,1973,1974,1977],{},[17,1975,1976],{},"Timeouts."," A long timeout on a function that hangs on a slow upstream keeps a billed instance busy until it gives up.",[31,1979,1981],{"id":1980},"step-4-firestore-reads","Step 4: Firestore reads",[14,1983,1984],{},"Read costs come from patterns, not single queries:",[611,1986,1987,1993,2015],{},[278,1988,1989,1992],{},[17,1990,1991],{},"Collection listeners on busy screens."," A dashboard that listens to every document in a collection pays for every change, for every open client. Paginate, filter, or listen to a summary document instead.",[278,1994,1995,1998,1999,2004,2005,350,2008,350,2011,2014],{},[17,1996,1997],{},"Counting by reading."," Use ",[88,2000,2003],{"href":2001,"rel":2002},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Ffirestore\u002Fquery-data\u002Faggregation-queries",[98],"aggregation queries"," (",[80,2006,2007],{},"count()",[80,2009,2010],{},"sum()",[80,2012,2013],{},"average()",") instead of downloading documents to count them.",[278,2016,2017,2020,2021,2024],{},[17,2018,2019],{},"Scheduled scans."," A job that reads a whole collection every five minutes to find a few changed documents should query on an indexed ",[80,2022,2023],{},"updatedAt"," field instead.",[31,2026,2028],{"id":2027},"step-5-trigger-fan-out-and-retry-storms","Step 5: Trigger fan-out and retry storms",[14,2030,2031],{},"Event-triggered functions can multiply quietly:",[611,2033,2034,2037,2040],{},[278,2035,2036],{},"A function that writes to the document that triggered it can re-trigger itself.",[278,2038,2039],{},"One write can fan out to several triggers, each of which writes again.",[278,2041,2042],{},"A function with retries enabled that fails on the same bad data keeps retrying, for hours or days, and every attempt is billed.",[14,2044,2045],{},"Look for invocation counts that are far higher than the user actions behind them, and for error rates that never drop.",[31,2047,2049],{"id":2048},"step-6-secrets-logs-and-images","Step 6: Secrets, logs and images",[14,2051,2052],{},"These are smaller lines, but they add up across many services:",[611,2054,2055,2061,2067],{},[278,2056,2057,2060],{},[17,2058,2059],{},"Secret Manager"," bills for active secret versions and for access operations. Disable or destroy versions you no longer use, and read a secret once per instance rather than once per request.",[278,2062,2063,2066],{},[17,2064,2065],{},"Cloud Logging"," charges for ingestion beyond the free monthly allotment. Logging full request payloads is expensive, and it can also write customer data into your logs.",[278,2068,2069,2072],{},[17,2070,2071],{},"Artifact Registry"," stores a container image for every function deploy. A cleanup policy keeps only the recent ones.",[31,2074,2076],{"id":2075},"step-7-ai-and-vertex-ai-usage","Step 7: AI and Vertex AI usage",[14,2078,2079],{},"If your app calls Gemini or another model, look at tokens per user action, not just total spend. Common fixes are caching repeated prompts, trimming the context you send, and putting a per-user or per-workspace limit on expensive features. If you resell AI features, check that your price covers your cost per call; that is a revenue leak, not a cloud cost, but it shows up in the same audit.",[31,2081,2083],{"id":2082},"rank-the-savings-then-decide","Rank the savings, then decide",[14,2085,2086],{},"Write every finding in one table and sort it by dollars a month:",[36,2088,2089,2109],{},[39,2090,2091],{},[42,2092,2093,2096,2100,2103,2106],{},[45,2094,2095],{},"Finding",[45,2097,2099],{"align":2098},"right","$\u002Fmonth",[45,2101,2102],{},"User-visible risk",[45,2104,2105],{},"Effort",[45,2107,2108],{},"How to roll back",[61,2110,2111,2131,2147],{},[42,2112,2113,2116,2119,2122,2125],{},[66,2114,2115],{},"Example: min instances on a nightly job",[66,2117,2118],{"align":2098},"measured",[66,2120,2121],{},"None",[66,2123,2124],{},"1 line",[66,2126,2127,2128,2130],{},"Set ",[80,2129,1880],{}," back",[42,2132,2133,2136,2138,2141,2144],{},[66,2134,2135],{},"Example: collection listener on the dashboard",[66,2137,2118],{"align":2098},[66,2139,2140],{},"Low",[66,2142,2143],{},"Half a day",[66,2145,2146],{},"Revert the query",[42,2148,2149,2152,2154,2156,2158],{},[66,2150,2151],{},"Example: 1 GiB on a 120 MiB function",[66,2153,2118],{"align":2098},[66,2155,2140],{},[66,2157,2124],{},[66,2159,2160],{},"Raise memory again",[14,2162,2163],{},"Apply the low-risk, high-dollar rows first. Leave anything on a latency-sensitive path until you've watched it in staging.",[31,2165,2167],{"id":2166},"when-to-get-help","When to get help",[14,2169,2170,2171,2174,2175,2179],{},"If the bill matters but nobody on the team has a free week, App369 runs this audit for a ",[88,2172,2173],{"href":1784},"fixed $750",", delivered in 5 business days with read-only, temporary access. You get the bill by service, the ranked savings table, a CSV of every service, and the exact commands to apply each change. Nothing in your project is changed. If you are also worried about who can read what, the ",[88,2176,2178],{"href":2177},"\u002Fblog\u002Ffirebase-security-guide-2026\u002F","Firebase Security Rules guide"," covers the access side.",[31,2181,2183],{"id":2182},"frequently-asked-questions","Frequently Asked Questions",[251,2185,2187],{"id":2186},"why-is-my-firebase-bill-so-high-when-traffic-is-low","Why is my Firebase bill so high when traffic is low?",[14,2189,2190],{},"Usually because something runs without traffic: minimum instances kept warm around the clock, scheduled functions that scan collections, or triggers that re-fire. Low traffic with a high bill points to background work or idle capacity, not to users.",[251,2192,2194],{"id":2193},"do-minimum-instances-cost-money-when-nobody-calls-the-function","Do minimum instances cost money when nobody calls the function?",[14,2196,2197],{},"Yes. A minimum instance is kept running so it can answer without a cold start, and it is billed while idle. Keep minimum instances only on functions where a user is waiting for the response.",[251,2199,2201],{"id":2200},"how-do-i-see-the-cost-of-each-cloud-function","How do I see the cost of each Cloud Function?",[14,2203,2204],{},"Turn on Cloud Billing export to BigQuery for actual spend by SKU, and use Cloud Monitoring's request count and billable instance time per Cloud Run service. 2nd gen functions appear as Cloud Run services, so each function's usage can be priced separately.",[251,2206,2208],{"id":2207},"will-cutting-costs-make-my-app-slower","Will cutting costs make my app slower?",[14,2210,2211],{},"Only if you cut on the wrong path. Rank each saving by user-visible risk: background jobs, webhooks and reports can usually scale to zero, while login, checkout and screen-loading functions may need warm instances.",[251,2213,2215],{"id":2214},"can-i-lower-my-firebase-bill-without-changing-code","Can I lower my Firebase bill without changing code?",[14,2217,2218],{},"Partly. Minimum instances, memory, concurrency and timeouts can be changed in configuration. Firestore read patterns, trigger loops and logging volume usually need code changes, and settings changed only in the console are overwritten by the next deploy if the code says otherwise.",[1660,2220,2221],{},"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 pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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":404,"searchDepth":405,"depth":405,"links":2223},[2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234],{"id":1789,"depth":405,"text":1790},{"id":1828,"depth":405,"text":1829},{"id":1873,"depth":405,"text":1874},{"id":1952,"depth":405,"text":1953},{"id":1980,"depth":405,"text":1981},{"id":2027,"depth":405,"text":2028},{"id":2048,"depth":405,"text":2049},{"id":2075,"depth":405,"text":2076},{"id":2082,"depth":405,"text":2083},{"id":2166,"depth":405,"text":2167},{"id":2182,"depth":405,"text":2183,"children":2235},[2236,2237,2238,2239,2240],{"id":2186,"depth":411,"text":2187},{"id":2193,"depth":411,"text":2194},{"id":2200,"depth":411,"text":2201},{"id":2207,"depth":411,"text":2208},{"id":2214,"depth":411,"text":2215},"2026-10-12T09:00:00.000Z","A line-by-line method for finding where a Firebase or Google Cloud bill goes: measure usage, price every Cloud Function and Cloud Run service, then rank savings by dollars a month and risk.",{"readingTimeStats":2244},{"text":2245,"minutes":2246,"time":2247,"words":2248},"7 min read",6.435,386100,1287,"\u002Fblog\u002Fhow-to-cut-your-firebase-bill-2026","10 min",{"title":1768,"description":2242},"blog\u002Fhow-to-cut-your-firebase-bill-2026","firebase cost, firebase pricing, cloud functions cost, cloud run cost, google cloud cost optimization, firestore reads","2026-10-12T10:00:00.000Z","https:\u002F\u002Fapp369.com\u002Fblog\u002Fhow-to-cut-your-firebase-bill-2026\u002F","v_wPlLxHTHTOyc-RE0EnxEsPoKnKGx8og3UJ9ksyPOs",[2258,2260,2262],{"keyword":5,"url":483,"title":5,"relevance":2259},75,{"keyword":488,"url":946,"title":488,"relevance":2261},15,{"keyword":950,"url":1764,"title":950,"relevance":2263},12,1792307201083]