The Hidden Monorepo Bug: Stale Firebase Functions
You've fixed a shared package, type-checked, and passed CI, yet your Firebase function ships stale. The bug isn't in your code, but in the packaging step. Learn how to diagnose and fix this common monorepo deployment issue.
On this page
- The Illusion of Freshness: Why Your Code Appears Current
- The Core Problem: Stale .tgz Archives
- The Deployment Gap
- Diagnosing the Stale Package
- The Fix: Forcing .tgz Regeneration
- 1. Explicit npm pack or yarn pack
- 2. Using Monorepo Tools (e.g., Lerna, Nx, Turborepo)
- 3. Custom Build Script
- Preventing Future Occurrences
If you're deploying Firebase functions from a monorepo, you might have encountered a particularly frustrating bug: a shared package fix lands, type-checks, and passes CI, but the deployed function still runs the old, stale code. The problem isn't in your code or your tests; it's a subtle interaction with how Firebase functions bundle dependencies, specifically when those dependencies are local packages within your monorepo.
The Illusion of Freshness: Why Your Code Appears Current
When you're working in a monorepo, it's natural to expect that once you update a shared utility package and your CI pipeline passes, those changes will be reflected everywhere that package is used. For many parts of a modern application, this assumption holds true. Your local development environment picks up the changes, your tests run against the new code, and your type-checker confirms everything is in order.
However, Firebase Cloud Functions introduce a wrinkle. Unlike other deployment targets that might build directly from your source or a pre-compiled artifact, Firebase functions, particularly when dealing with local file: dependencies in package.json, have a specific bundling mechanism. They package each local dependency as a .tgz archive. This archive is then included in the final function bundle that gets uploaded to Google Cloud.