Webinar replay: The migration takes 2 weeks. Deciding to do it takes 6 months.

How to Migrate a Firebase Backend (Functions, Firestore, Auth) to Kubernetes in Your Own AWS or GCP Account

A piece-by-piece plan to move Firebase Cloud Functions, Firestore and Firebase Auth onto Kubernetes in your own AWS, GCP, Azure or Scaleway account - including the exact order to migrate in, how to export Firebase Auth password hashes without forcing resets, and what the new bill actually looks like.

Romaric Philogene
CEO & Co-founder
OCT 31, 2026 · 13 MIN
How to Migrate a Firebase Backend (Functions, Firestore, Auth) to Kubernetes in Your Own AWS or GCP Account

Key Points:

  • Order: API layer, then Cloud Functions, then Firestore, then Firebase Auth last. Teams that start with the database stall, because Firestore security rules were their authorization layer and mobile clients talk to Firestore directly.
  • Cloud Functions are the easy part. HTTP functions become routes in a container, triggers become queue consumers, schedules become Kubernetes CronJobs.
  • Firestore has no drop-in replacement. Most teams pick PostgreSQL with JSONB, and you rebuild onSnapshot listeners and offline persistence yourself.
  • Auth users move without password resets. firebase auth:export emits Firebase's modified scrypt hashes, which Ory and SuperTokens can import. Keycloak needs a custom hash provider, Zitadel and AWS Cognito need lazy migration.
  • No platform team required. Qovery runs Kubernetes in your own AWS, GCP, Azure or Scaleway account, so you keep git-push deploys and preview environments while the bill and the region stay yours.

Qovery · Infrastructure control plane
Kubernetes, operated through one governed API
Learn more

Most Firebase migrations I hear about stall in month two, and almost always for the same reason: the team started with the database. The order that works is API layer, then Cloud Functions, then Firestore, then Auth, and the rest of this article explains why.

The reader I have in mind is a tech lead or CTO who hit a cost ceiling or a residency clause (an EU customer, a hospital, a public-sector RFP, a "deploy in our account" request) and was told "just move to Kubernetes" with no plan. Here is the plan, with real unit prices.

Why do teams migrate off Firebase to Kubernetes in their own cloud account?

Three triggers push teams off Firebase: a per-operation bill that grows with traffic patterns instead of compute, residency requirements Firebase Auth cannot meet, and customers who want the stack in their region, their account, or on-prem. Firebase is a good product. It stops matching those constraints.

  • Cost shape. Firestore bills per operation. In us-central1 that is $0.03 per 100,000 document reads, $0.09 per 100,000 writes, $0.01 per 100,000 deletes, after a free 50,000 reads and 20,000 writes per day (Google Cloud Firestore pricing). A chatty client or a fan-out read pattern multiplies that line without adding any compute.
  • Residency. You pick a Firestore location at creation, and Google states "once you provision a database instance, you cannot change its location setting" (Firestore locations). Auth is worse: "The Firebase Authentication service is run only from US data centers" (Privacy and Security in Firebase).
  • Compliance and lock-in. EU-only clauses, healthcare buyers and public-sector RFPs ask for data in a named region or the customer's own account, and every month of growth makes Firestore's data model harder to leave.

The honest counterpoint: if you are pre-product-market-fit or your traffic is low, stay on Firebase, or look at Supabase or a self-hosted Appwrite. This article is for teams past that point.

What exactly are you replacing when you migrate off Firebase?

A Firebase backend is six or seven products behind one SDK, and each has its own replacement path. Map all of them first, because the hardest piece is usually the clients that call Firestore directly, not the database.

Firebase componentOwn-account replacementDifficultyWhat breaks in the clientEffort (my estimate)
Cloud FunctionsContainerized services on Kubernetes + SQS, Pub/Sub, NATS or KafkaLowCallable function URLs and SDK calls1-4 engineer-weeks
FirestorePostgreSQL (JSONB) or MongoDB in your accountHighEvery direct read, write and listener4-12 engineer-weeks
Security rulesAuthorization in your API layerHighNothing visible, until a rule is missed2-6 engineer-weeks
Firebase AuthOry, SuperTokens, Keycloak, Zitadel, Authentik, or AWS CognitoMediumSign-in flows and token format2-6 engineer-weeks
Cloud Storage for FirebaseS3, GCS, Azure Blob or Scaleway Object StorageLowUpload SDK calls and download URLs1-2 engineer-weeks
HostingCDN + object storage, or a container serving the frontendLowNothingDays
Remote ConfigUnleash, Flagsmith or another OpenFeature providerLowFlag readsDays
Cloud Messaging (FCM)Usually keep itNoneNothingNone

The effort ranges come from what I've seen on small teams and will vary with your codebase. Keep FCM: it is the least coupled piece, and Android push goes through it anyway.

Mobile apps are the hidden long pole. Old app versions keep calling Firestore directly until users update, so plan to support both paths for weeks.

What order should you migrate Firebase in, and why does Auth go last?

Run it as a strangler-fig in five phases: stand up the cluster, put an API layer in front of Firebase, port Functions, dual-write and flip Firestore, then migrate Auth. Auth goes last because you can roll back every other phase quietly, while a bad auth cutover logs out your whole user base at once.

  1. Provision the platform. Create the cluster and CI/CD in your own AWS or GCP account (Azure and Scaleway work the same way). Deploy one hello-world service and prove logs, metrics and backups before anything else moves.
  2. Introduce an API layer. Add a backend-for-frontend so clients stop talking to Firestore directly. Every later phase depends on it, and it holds most of the client work.
  3. Port Cloud Functions service by service behind that API, with Firestore still the store.
  4. Move the data. Dual-write to the new database, backfill history, shadow-read and compare, then flip reads and retire Firestore.
  5. Migrate Auth with hash import or lazy migration, accept both token issuers for a window, then revoke Firebase sessions.

Give each phase a rollback trigger tied to a metric: error rate, p99 latency, or read divergence during shadow reads. The failure modes I see most are auth first, functions ported 1:1, and forgetting that rules were the authorization layer.

How do you migrate Firebase Cloud Functions to Kubernetes?

Each HTTP or callable function becomes a route in a normal containerized service, each Firestore trigger becomes a consumer on a queue, and each scheduled function becomes a Kubernetes CronJob. Most of the work is consolidation.

  • Group by domain. Dozens of tiny functions usually belong in two to four services built on Express, Fastify, NestJS or FastAPI.
  • Make triggers explicit. Replace onCreate, onUpdate and onDelete triggers with a publish from your API layer to SQS, Pub/Sub, NATS or Kafka, or with change data capture. Teams underestimate this step every time.
  • Schedules become CronJobs. Make each job idempotent, since Kubernetes can run a CronJob twice.
  • Retries become your job. Firebase background functions are not retried by default, but one "retry on failure" flag gives you retries until success or the retry window ends (Firebase docs). Your consumers need explicit retry, backoff and dead-letter handling.
  • Secrets move from functions:config or Firebase secrets to Kubernetes secrets backed by AWS Secrets Manager or GCP Secret Manager.

Always-on pods remove most cold starts but cost money when idle, while functions scale to zero. Cloud Run, which 2nd gen Cloud Functions now run on, is a fair halfway house if you stay on GCP, but it does not solve multi-cloud, on-prem or customer-account deployments.

What should you replace Firestore with, and how do you move the data?

No database is a drop-in Firestore replacement. Most teams pick PostgreSQL with JSONB, which keeps document-style ergonomics and adds transactions, joins and a single compliance story. MongoDB is the closest match if you want to avoid re-modeling.

OptionData model fitReal-timeTransactionsResidency controlOps burdenManaged optionCost shape
PostgreSQL + JSONBGood after re-modelingLISTEN/NOTIFY, or a layer like Supabase RealtimeFull ACIDAny regionLow on RDS, Aurora or Cloud SQLAmazon RDS/Aurora, Cloud SQL, Azure DatabaseProvisioned
MongoDBClosest to FirestoreChange streamsMulti-documentAny regionMediumMongoDB Atlas, in your chosen cloud and regionProvisioned
Amazon DocumentDBMongo-compatibleChange streamsMulti-documentAWS regionsLowYes, AWS onlyProvisioned
DynamoDBKey-value, needs access-pattern designStreamsLimitedAWS regionsLowYes, AWS onlyPer-request or provisioned
CockroachDBRelationalChangefeedsFull ACIDMulti-region by designMediumSelf-hosted or managedProvisioned
Firestore behind your APIUnchangedonSnapshot server-sideYesFixed at creationNoneNoPer-operation

Re-model before you export. Subcollections and denormalized documents rarely map cleanly, and Firestore's 1 MiB document cap (Firestore quotas) probably left workarounds in your schema you can now remove.

Move the data in two passes. Run gcloud firestore export gs://your-bucket for the historical snapshot (export docs), transform and load it, then let dual-writes from the API layer cover the delta. Shadow-read both stores, alert on divergence, and flip reads only when divergence sits at zero.

Tell stakeholders what you lose before you start:

  • Real-time listeners. onSnapshot has no equivalent. Plan WebSockets or SSE from your services, fed by Postgres LISTEN/NOTIFY or a layer like Centrifugo.
  • Offline persistence. The mobile SDKs' local cache and offline writes are a feature you rebuild or consciously drop.
  • Security rules. Firestore rules were your authorization layer. Write each rule as a test against the new API, and don't cut over until the suite passes.
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.

How do you migrate Firebase Auth users without forcing password resets?

Export users with firebase auth:export, grab your project's hash parameters from the console, and import them into a provider that can verify Firebase's modified scrypt. Where your provider can't, verify passwords against Firebase on each user's first sign-in and re-hash.

Step 1: export. Run:

BASH
firebase auth:export users.json --format=json

The command exports to JSON or CSV, and only scrypt-hashed passwords come out. Accounts hashed with another algorithm export with empty passwordHash and salt fields (Firebase CLI auth docs).

Step 2: get the hash parameters. In the Firebase console, go to Authentication > Users, click the three-dot menu above the users table, and open the password hash parameters. You get base64_signer_key, base64_salt_separator, rounds and mem_cost, unique per project.

Step 3: pick the import path. Firebase uses "an internally modified version of scrypt", not stock scrypt, with a reference implementation at github.com/firebase/scrypt (archived in June 2025).

  • Ory Kratos compares Firebase scrypt hashes natively using a $firescrypt$ format and re-hashes to your configured algorithm (Ory import docs).
  • SuperTokens added import of Firebase password hashes in core 4.0.0 (SuperTokens changelog).
  • Keycloak ships with Argon2 and PBKDF2 only, so you write a custom PasswordHashProvider that implements Firebase scrypt.
  • Zitadel says it "does not have a verifier for Firebase's custom scrypt format" and documents a just-in-time migration instead (Zitadel Firebase guide).
  • AWS Cognito uses the Migrate User Lambda trigger: at sign-in, your Lambda checks the password against Firebase and Cognito creates the user with that password.

Lazy migration works with any provider: validate each user against Firebase once at sign-in, write the new hash, and never call Firebase for that user again. Users who stay away all window get a reset email.

What does not transfer cleanly:

  • Federated identities (Google, Apple, SAML) need new OAuth client registrations and account linking by verified email.
  • Custom claims, MFA enrollments, phone factors and anonymous accounts each need a re-enrollment plan.
  • Tokens. Firebase ID tokens are JWTs issued by securetoken.google.com/<project-id>. Your API needs middleware that accepts both issuers, and on mobile that means an app release and weeks of overlap until old versions fade out.

What does Kubernetes actually cost compared with Firebase, and what do you have to operate?

You trade a per-operation bill with zero idle cost for a fixed infrastructure floor plus people time. The move pays for itself on cost alone only above a traffic level you can compute from published unit prices, and for many teams residency is the real reason.

Line itemFirebase (per-operation, zero idle)Own-account Kubernetes on AWS or GCP (fixed floor)
Control planeNoneEKS $0.10 per cluster-hour (AWS); GKE $0.10 per cluster-hour with a $74.40 monthly credit covering one zonal or Autopilot cluster (Google Cloud)
Compute$0.40 per million requests after 2M free, plus per-second CPU and memory (Cloud Run)Two or three worker nodes at on-demand or committed prices
Database$0.03 / $0.09 / $0.01 per 100K reads / writes / deletes (Firestore)Managed instance-hours plus storage (RDS, Cloud SQL)
Networking10 GiB/month Firestore egress free, then Google Cloud ratesLoad balancer, plus AWS NAT Gateway at $0.045/hour and $0.045/GB processed in US East (Ohio) (AWS VPC pricing)
Identity50,000 MAU free on Identity Platform, then $0.0055/MAU (Identity Platform)Self-hosted provider on the cluster, or Cognito
PeopleClose to zeroUpgrades, CVE patching, autoscaling, IAM, observability, on-call

The break-even method. Put last month's Firebase invoice next to the fixed floor: about $73 a month per EKS or GKE cluster (730 hours at $0.10) before credits, plus nodes, database, NAT and load balancer at your region's prices, plus people time. At $0.03 per 100,000, a billion Firestore reads cost $300, so read volume alone rarely justifies a move. Fan-out writes and egress matter more.

People are the biggest line. The CNCF 2024 survey found 80% of organizations run Kubernetes in production, with cultural and operational challenges now the top hurdle.

Own-account savings come from commitments in your name (AWS Savings Plans cut up to 72% off on-demand per AWS, GCP commitments up to 55%, or 70% on memory-optimized machines per Google Cloud), right-sized autoscaling, spot nodes for non-production, and stopping non-production environments at night.

How do you keep the Firebase developer experience after moving to Kubernetes?

What teams fear losing is firebase deploy and instant preview channels, more than the database. You keep both by putting a platform in front of the cluster instead of handing every developer kubectl, Helm and a cloud console login.

The baseline to keep: git push to deploy, a URL per pull request, logs without kubectl, and developers managing their own variables and secrets.

DIY (ArgoCD + Helm + Backstage)Managed PaaS (Render, Railway, Heroku)Qovery in your own account
Residency controlFullLimited to the vendor's regionsFull: your account, your region
Who owns the cloud billYouThe vendorYou, including committed-use discounts
Preview environmentsYou build themYesYes, per pull request
Cluster upgradesYour teamVendor, invisibleManaged by Qovery
RBACYou build itPer vendorPer environment
Time to first deployWeeks to monthsMinutesSame day

A managed PaaS brings back the problem you left Firebase to solve, since your data sits in someone else's account. DIY is a legitimate choice if you already have a strong platform team, as long as you price in who maintains it.

This is the gap we built Qovery for. Qovery installs and operates Kubernetes in your own AWS, GCP, Azure or Scaleway account, or connects to a cluster you already run, including self-managed and on-prem. You get git-push deployments, preview environments per pull request, auto-stop for non-production environments, managed cluster upgrades, per-environment RBAC, and databases backed by your cloud's managed services. Small teams ship on Kubernetes without managing it directly and without hiring a dedicated DevOps engineer first.

To be explicit about the boundary: Qovery runs the Kubernetes and application layer. It does not migrate your Firestore documents or import your Firebase Auth users. Those stay your phases 4 and 5.

How do I run this migration with Claude Code or Cursor using Qovery?

Hand the infrastructure half to your coding agent: install the Qovery Agent Skills once, then ask in plain language for a cluster in your own AWS or GCP account and a deploy of the services you ported from Cloud Functions. The agent asks you to approve each action.

BASH|Global install for Claude Code, Cursor, Codex, OpenCode, Gemini CLI
curl -fsSL https://skill.qovery.com/install.sh | bash

# Or scoped to this repository only
curl -fsSL https://skill.qovery.com/install.sh | bash -s -- --project

# Qovery MCP Server in Claude Code (OAuth, read-only by default)
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242

# Write access, only when you want it (also enable it in the Qovery Console)
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242

The skills deploy, and the MCP Server operates what already exists. qovery-onboard sets up the cluster in your account, qovery-deploy ships your ported services, and qovery-preview replaces Firebase preview channels with per-pull-request environments. qovery-troubleshoot, qovery-optimize, qovery-speedup and qovery-terraform cover the rest.

Then ask, for example: "deploy this ported Functions service to my GCP account with Qovery and give me a preview environment per pull request". See the AI agent quickstart and the Claude Code integration.

Frequently asked questions
Can I export Firebase Auth users with their passwords?

Yes. firebase auth:export users.json --format=json exports each user's scrypt hash and salt, and the project's hash parameters sit under Authentication > Users in the Firebase console. Ory and SuperTokens can import them; for Zitadel or Cognito, use lazy migration.

Is there a self-hosted alternative to Firestore?

No self-hosted database replicates Firestore's API. MongoDB is the closest document model and PostgreSQL with JSONB the most common choice. For a Firebase-like product, Supabase and Appwrite both self-host.

Does Firebase let me choose where my user data is stored?

For Firestore, yes, at creation and never again. For Firebase Authentication, no: Google states the service "is run only from US data centers".

How much does it cost to replace Firebase with Kubernetes on AWS or GCP?

The control plane is about $73 a month per EKS or GKE cluster (GKE's free credit covers one zonal or Autopilot cluster), plus nodes, a managed database, a load balancer and NAT or egress. Compare that floor plus people time against your Firebase invoice line by line.

How do I replace Firestore real-time listeners and offline persistence after migrating?

Serve WebSockets or server-sent events from your services, fed by Postgres LISTEN/NOTIFY, MongoDB change streams, or Centrifugo. Offline persistence has no off-the-shelf equivalent, so build a local cache and sync queue or drop it on purpose.

Do I need a DevOps engineer to run Kubernetes after leaving Firebase?

Not if a platform handles the cluster. Qovery runs Kubernetes in your own AWS, GCP, Azure or Scaleway account and handles upgrades. If you build it yourself with ArgoCD, Helm and Backstage, plan for at least one owner.

Romaric Philogene
About the author
Romaric Philogene

Romaric founded Qovery to make Kubernetes accessible to every engineering team. He writes about platform strategy, developer experience, and the future of cloud infrastructure.

Next step

Ship faster on infrastructure you control.

Qovery gives your team self-service deployments on your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.