<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivan Tsomo</title>
    <description>The latest articles on DEV Community by Ivan Tsomo (@ivan_tsomo_c71556b8abba1f).</description>
    <link>https://dev.to/ivan_tsomo_c71556b8abba1f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4210849%2Fc7b060d0-7679-4d02-b85e-d442b87d1f81.jpeg</url>
      <title>DEV Community: Ivan Tsomo</title>
      <link>https://dev.to/ivan_tsomo_c71556b8abba1f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivan_tsomo_c71556b8abba1f"/>
    <language>en</language>
    <item>
      <title>73% of firebase-admin downloads are still on v13 or older, 4 months after v14</title>
      <dc:creator>Ivan Tsomo</dc:creator>
      <pubDate>Tue, 27 Oct 2026 12:25:57 +0000</pubDate>
      <link>https://dev.to/ivan_tsomo_c71556b8abba1f/73-of-firebase-admin-downloads-are-still-on-v13-or-older-4-months-after-v14-2acf</link>
      <guid>https://dev.to/ivan_tsomo_c71556b8abba1f/73-of-firebase-admin-downloads-are-still-on-v13-or-older-4-months-after-v14-2acf</guid>
      <description>&lt;p&gt;On June 8, 2026, &lt;code&gt;firebase-admin&lt;/code&gt; 14 shipped and removed the namespaced API: &lt;code&gt;admin.firestore()&lt;/code&gt;, &lt;code&gt;admin.auth()&lt;/code&gt;, &lt;code&gt;admin.messaging()&lt;/code&gt; and friends are gone. Every call has to move to the modular entry points (&lt;code&gt;getFirestore()&lt;/code&gt;, &lt;code&gt;getAuth()&lt;/code&gt;, &lt;code&gt;getMessaging()&lt;/code&gt;…).&lt;/p&gt;

&lt;p&gt;Four months later, I looked at the npm registry's per-version download counts for the last week.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqc0ymg28swi0ue1u58ao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqc0ymg28swi0ue1u58ao.png" alt="firebase-admin weekly downloads by major version" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of &lt;strong&gt;8,995,732&lt;/strong&gt; downloads that week:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Major&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;v14 (current)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26.9%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v13&lt;/td&gt;
&lt;td&gt;47.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v12&lt;/td&gt;
&lt;td&gt;19.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v11&lt;/td&gt;
&lt;td&gt;4.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v10 and older&lt;/td&gt;
&lt;td&gt;1.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So &lt;strong&gt;73% of installs are still on v13 or older.&lt;/strong&gt; v13 alone is downloaded almost twice as often as the version that replaced it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A caveat before anyone jumps in:&lt;/em&gt; npm downloads are not projects. Most of these come from CI pipelines reinstalling dependencies, so one busy repository counts many times. But that also means these are &lt;strong&gt;builds that run every day&lt;/strong&gt; on a version line that no longer gets new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changed
&lt;/h2&gt;

&lt;p&gt;The modular API has existed since v10, so most of the migration is mechanical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// v13 and older (namespaced)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kd"&gt;as &lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serverTimestamp&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// v14 (modular)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initializeApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin/app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getFirestore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FieldValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin/firestore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getAuth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serverTimestamp&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getAuth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things make it less trivial than it looks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 22 is required.&lt;/strong&gt; If your &lt;code&gt;engines.node&lt;/code&gt; still allows Node 18 or 20, the upgrade is not just a code change, it is a runtime change for your servers, functions and CI images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peer dependencies.&lt;/strong&gt; If you use Cloud Functions, &lt;code&gt;firebase-functions&lt;/code&gt; 6.x does not accept &lt;code&gt;firebase-admin&lt;/code&gt; 14 in its peer range. You need &lt;code&gt;firebase-functions&lt;/code&gt; 7.x at the same time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And a few patterns cannot be migrated by search-and-replace at all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an &lt;code&gt;admin&lt;/code&gt; namespace &lt;strong&gt;exported&lt;/strong&gt; and used by other modules (&lt;code&gt;module.exports = { admin }&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;admin.firestore&lt;/code&gt; passed around as a value, or used both as a function and as a namespace in the same file;&lt;/li&gt;
&lt;li&gt;dynamic access like &lt;code&gt;admin[service]()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are exactly the places where a bulk regex breaks a codebase silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why teams stay behind
&lt;/h2&gt;

&lt;p&gt;From the projects I looked at, the reasons are boringly human:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nothing is broken today.&lt;/strong&gt; v13 still works, so the upgrade never wins against feature work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diff touches many files.&lt;/strong&gt; Every file that imports &lt;code&gt;firebase-admin&lt;/code&gt; changes, which makes the pull request scary to review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The runtime bump is the real blocker.&lt;/strong&gt; Node 22 means touching deployment config, not just code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One example that encouraged me: I opened an issue on an open-source project explaining exactly which calls had to move. Three days later, the maintainer opened a pull request upgrading to v14 and Node 22, and merged it the next day (&lt;a href="https://github.com/crowdcad/crowdcad/pull/129" rel="noopener noreferrer"&gt;crowdcad#129&lt;/a&gt;). The hard part was never the code. It was knowing precisely what to change and trusting that nothing else would break.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to migrate without guessing
&lt;/h2&gt;

&lt;p&gt;Whatever tool you use, the safe sequence is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upgrade Node.js to 22 first, in CI and production, while still on v13.&lt;/li&gt;
&lt;li&gt;Move imports to the modular entry points &lt;strong&gt;file by file&lt;/strong&gt;; v13 supports both styles, so you can ship this before bumping the version.&lt;/li&gt;
&lt;li&gt;Search for the patterns above (exported namespace, &lt;code&gt;admin[...]&lt;/code&gt;, &lt;code&gt;admin.firestore&lt;/code&gt; used as a value) and fix them by hand.&lt;/li&gt;
&lt;li&gt;Bump &lt;code&gt;firebase-admin&lt;/code&gt; to &lt;code&gt;^14&lt;/code&gt; (and &lt;code&gt;firebase-functions&lt;/code&gt; to &lt;code&gt;^7&lt;/code&gt; if you use it), regenerate the lockfile, then run your type checker and tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Full disclosure: I built a tool for this
&lt;/h2&gt;

&lt;p&gt;I'm Ivan, a backend developer in Cameroon. I got tired of doing these upgrades by hand, so I built &lt;strong&gt;UpstreamFix&lt;/strong&gt;, an open-source (MIT) CLI that does steps 2 and 3 for you and refuses to guess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx upstreamfix migrate firebase-admin@14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It reads your code through the TypeScript AST, shows a preview of every change, and lists anything it cannot migrate safely (like an exported &lt;code&gt;admin&lt;/code&gt; namespace) as a manual finding instead of rewriting it. Nothing is written unless you ask for it, and it never merges anything.&lt;/p&gt;

&lt;p&gt;The source is on GitHub: &lt;a href="https://github.com/ivanDev237/upstreamfix" rel="noopener noreferrer"&gt;ivanDev237/upstreamfix&lt;/a&gt;. Feedback and bug reports are very welcome, especially on code it gets wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your turn
&lt;/h2&gt;

&lt;p&gt;If you are still on v13 (or v12), what is actually keeping you there: the Node 22 bump, &lt;code&gt;firebase-functions&lt;/code&gt;, the size of the diff, or just time? I'm curious whether the blocker is the same for everyone.&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>node</category>
      <category>javascript</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
