Open-source alternative to Cloud Storage for Firebase

Cloud Storage for Firebase now requires the Blaze plan, so teams look for self-hosted file storage they control. This page maps the options, the S3-compatible backends and the access rules to rebuild.

On this page

Open-source alternative to Cloud Storage for Firebase: the short answer

If your Firebase app keeps files in Cloud Storage and that now requires the Blaze plan, or if the files must stay on infrastructure you control, Supabase Storage, Appwrite Storage and PocketBase file fields can each replace it. All three can keep bytes on local disk or in an S3-compatible store, so the choice depends less on where files sit and more on which backend already holds your users, data and functions. The harder part is not copying objects. It is rebuilding the access rules that Firebase Storage Security Rules enforced on each path, and proving that a user who could read a file yesterday still can, and a user who could not still cannot, after cutover.

Supabase Storage fits teams that are moving the rest of the backend to Postgres, because object access can be tied to the same Auth users and row-level policies. Its Docker configuration is Apache-2.0 and bundles a Storage service that you deploy and patch yourself. Appwrite Storage fits teams that want Auth, databases, storage and functions in one product, with a Firebase migration path, but its 2.x line changed the underlying engine, so test uploads and permissions on the version you install. PocketBase file fields are the simplest option, with files in pb_data/storage by default and optional S3-compatible storage, but PocketBase is pre-1.0 and volunteer-maintained, so weigh that against a small app. Confirm each platform's current storage limits, backup behavior and S3 configuration with its documentation before you choose.

Which open-source storage option covers each Cloud Storage capability

This table maps the main Cloud Storage for Firebase capabilities to Supabase Storage, Appwrite Storage and PocketBase file fields. Read each row as a question to confirm in your own environment: where a cell says to confirm, the feature was not documented in the sources we reviewed for this page, so test it before you commit. The main takeaway is that the file transfer itself is well covered, but Firebase security rules have no direct equivalent and must be rewritten.

CapabilitySupabase StorageAppwrite StoragePocketBase file fields
Upload and downloadObject upload and download through the Storage service behind the self-hosted API gatewayUpload and download through the Storage API and client SDKsFiles attached to records and served through the PocketBase API
Buckets or pathsBuckets with object paths, managed in Studio and the APIBuckets with file IDs and permissions set per bucketFiles stored under pb_data/storage on local disk by default
Security rulesNo direct equivalent to Firebase rules; access is rewritten as Postgres row level security policies on storage tablesNo direct equivalent; permissions are set per bucket and per file at creation and must be rewrittenNo direct equivalent; access follows collection API rules on the record that holds the file
Image transformationimgproxy service included in the Docker Compose stack; confirm the transformation options you needConfirm whether image previews and transformations meet your needs in the target releaseNot documented as a built-in feature; plan a separate resizing step or service
Resumable uploadsConfirm support for resumable uploads in your Storage version and client SDKConfirm support for resumable uploads in your target release and SDKConfirm upload behavior for large files in your deployment before relying on it
Object lifecycleConfirm expiry or lifecycle rules in the self-hosted release; plan cleanup jobs if absentConfirm lifecycle rules in the target release; plan cleanup jobs if absentNot documented; plan cleanup with a scheduled job or a hook
BackupStorage objects are separate from the database, so back up both; copy existing objects from a hosted project using the documented migration guideBack up the storage volume or configured object storage alongside the databaseDashboard backups can be stored locally or in S3-compatible storage, with slight performance impact during backups
External object storageObject storage backend configurable; confirm the S3-compatible backend your team choosesConfirm the S3-compatible storage configuration for your deploymentSwitchable to S3-compatible storage from the dashboard file settings

When Supabase Storage, Appwrite Storage or PocketBase fits

Each of these three options keeps uploads inside your own infrastructure and ties file access to the rest of the backend. They differ in how access is enforced, where bytes sit by default and how far the storage layer can grow, so the choice depends on your file volume, your access model and how many servers you want to run.

Supabase Storage

Supabase Storage keeps object metadata in Postgres, so access policies can be written against the same tables and users that your app already queries. The self-hosted Docker Compose stack includes the Storage service and imgproxy for image transformations, and the project is licensed under Apache-2.0. Check whether your file workload needs imgproxy, since you can remove unused services from docker-compose.yml, and confirm how object bytes are stored (local disk or an S3-compatible backend) in your chosen configuration. The trade-off is that you also operate Postgres, which means your team owns storage migrations and backups.

Appwrite Storage

Appwrite Storage organizes files into buckets, each with its own permissions, so you can separate public assets from private uploads without writing database rules. The project is licensed under BSD-3-Clause, and the stack ships through both the Docker Compose file and the official Helm chart. Confirm how the Helm chart's object storage backend is configured for your environment, because its built-in object storage runs a single replica without replication or failover. Plan for a managed or operator-run object store if files are production critical.

PocketBase file fields

PocketBase attaches files to records through file fields and stores them in pb_data/storage on the local file system by default. You can switch to external S3-compatible storage from the dashboard's file storage settings, which lets you point at a store such as Garage or SeaweedFS. PocketBase is MIT licensed, but the FAQ describes it as a single-server, vertically scaled project. Before you adopt it, weigh that limit against your upload volume, and note that the documentation warns it is not yet recommended for production critical applications.

Choosing between the three

Pick Supabase Storage when file access must follow Postgres row policies and you accept running Postgres. Pick Appwrite Storage when you want bucket-level permissions and a broader service set in one product. Pick PocketBase file fields when the app is small, runs on one server and can tolerate pre-1.0 upgrade steps. Test your largest expected upload and download pattern on each candidate before deciding.

Local disk or S3-compatible storage: how the backing store changes operations

On a single server, file storage is usually a directory on the host's disk. PocketBase is the clearest case: it stores uploads in pb_data/storage on the local file system by default, so the data directory is the unit you protect. Appwrite and Supabase can also write to local volumes in their Docker setups, which keeps the architecture small but ties durability to one machine.

  • Backup scope: the file directory and the database must be backed up together, or metadata will point at missing objects or the reverse.
  • Replication: none by default. A disk failure without a copy is a loss, so a second copy on another host or disk is an operator task.
  • Capacity: growth is limited by the server's disks, and expanding them is a maintenance event.
  • Restore testing: a restore into a clean host should be rehearsed, since PocketBase's production guide notes that backups can slightly degrade performance while they run.
  • Single point of failure: the host, its disk and its network path all fail together.

Small internal apps with modest volumes often accept this trade-off. Confirm the backup schedule, the off-host copy and the time it takes to restore to a fresh server before go-live.

Rebuilding Firebase Storage security rules as storage policies

Firebase Storage rules match file paths and evaluate the caller's auth token and request data, such as the content type or size, before allowing a read or write. The open-source platforms express the same intent differently, so the rules cannot be copied across line by line. In Supabase, storage objects are rows in a Postgres table, so access is written as row level security policies on the storage schema, typically keyed on the authenticated user ID stored in the object path or metadata. In Appwrite, access is granted through bucket-level and file-level permissions that name users, teams, roles or labels. In PocketBase, a file is a field on a record, so the collection rules that govern the record also govern the file, and you must decide whether file access should follow the record or be separate. Start with a written inventory of every Firebase rule: the path pattern, the condition, the operation (read, write, delete), and any custom claims or request fields it depends on. Each entry should map to one target construct, and any rule with no clean equivalent becomes a design decision to record before work begins.

Test each rebuilt policy before cutover, not after. For every path in the inventory, run requests from three identities: a signed-in user who owns the object, a signed-in user who does not, and an anonymous client. Add a fourth case for cross-user access attempts that try to guess or enumerate paths belonging to others. Record the expected result for each request and compare it with what the target platform returns, including the HTTP status and whether the file body is actually returned. Pay particular attention to list operations, signed or public URLs, and deletes, because these are the most common places where a policy that looks correct still leaks or blocks access. Confirm each platform's current behavior for these cases against its own documentation and your version, since storage features change between releases. Keep the test results as evidence for your change record, and rerun the suite after every upgrade of the storage service.

How to move Firebase Storage files without breaking links

The sequence inventories every file, freezes or dual-writes uploads, copies objects with checksums intact, and rewrites download references so users keep working after the cutover. The result is a verified copy in the new store and a documented path back if a check fails.

  1. Inventory buckets, paths and references

    Engineering lists every Cloud Storage bucket, folder prefix and file path the app uses, and records where each path is referenced: database rows, client code, emails, exported PDFs and third-party links. Owners of each bucket are named in the inventory. The output is a spreadsheet or manifest with one line per prefix, its size, its access rule and its consumers. If the inventory misses a consumer, links will break later, so the team should search code and stored data for the bucket name as well as the path prefix.

  2. Freeze or dual-write new uploads

    Before copying, the team chooses between a short write freeze for each bucket and dual-writing, where the app sends new uploads to both Firebase and the target store during the transition. Freezing is simpler to verify, while dual-writing keeps uploads flowing but needs code changes and a reconciliation pass. The chosen option is written into the cutover plan with the people who approve it. Done means that every upload path in the app is either blocked for the window or writes to both stores, confirmed by a test upload on each path.

  3. Copy objects to the target store

    For Supabase, the supabase-community firebase-to-supabase repository includes scripts for Storage files, and the Supabase self-hosting guide describes copying Storage objects from a platform project. For Appwrite, the Migrations feature imports Firebase projects, and the team should confirm which file types and sizes it handles in its own environment. Copies go into the bucket or storage path on local disk or S3-compatible storage such as Garage or SeaweedFS, with the same folder structure where possible. Done means the target holds every object in the inventory, with a log listing any failures for retry.

  4. Validate checksums and content types

    The team compares each copied object with its source using checksums, file sizes and stored content types, since some copy paths can alter metadata. Files with a wrong or generic content type will download with incorrect headers, so the check should cover images, PDFs and video specifically. Records that fail are re-copied and checked again. Done means a report shows zero unexplained mismatches per prefix, and the failures that remain are listed with an owner and a decision about each one.

  5. Rewrite stored and client download URLs

    Firebase download URLs with tokens and bucket paths are stored in database rows, documents and client configuration. Engineering writes a script that maps old URLs or object paths to the new storage endpoint, runs it against a copy of the production data first, and checks a sample of records by opening the rewritten links. Access rules must be rebuilt on the new platform at this point, because signed or public links behave differently. Done means that a test set of old references resolves to the new objects with the expected access behavior.

  6. Switch the app configuration and DNS

    The team changes the storage endpoint, bucket names and any custom domain in the app configuration, then deploys to a staging environment and runs the critical user journeys that load files. If the storage hostname is served under a custom domain, DNS and TLS are switched in a planned window with a rollback record ready. The write freeze or dual-write is lifted only after these checks pass. Done means that staging and production both load files from the new store and the monitoring shows no failed file requests for an agreed observation period.

  7. Retire the old bucket after a hold period

    The old Firebase bucket stays read-only and in place for a hold period the team sets in advance, so it can be restored if a missed reference appears. The team then archives a final export, records the deletion decision, and removes the bucket and its billing exposure. Because Cloud Storage for Firebase requires the Blaze plan, the team should confirm with its own billing records that no remaining service depends on the bucket before deletion. Done means the bucket is deleted or archived and the inventory is updated to show the new location of every prefix.

Questions buyers ask before replacing Firebase Storage

What does replacing Firebase Storage cost, and what drives it up?

The cost comes from four components: the storage hardware or S3-compatible service that holds the files, the one-time work to move objects and rebuild access rules, the backups, and the people who operate and patch the stack. The one-time work is usually the largest and depends on how many files exist, how large they are and how many rules must be rewritten. Recurring costs are the storage capacity, bandwidth, backup copies and operator time. Ask any quote to itemize each component separately, state the file count and total size it assumes, and name the store (Supabase Storage, Appwrite Storage, PocketBase file fields, local disk or an S3-compatible store such as Garage or SeaweedFS) so you can compare recurring costs directly.

Can our team move Firebase Storage files without outside help?

A team with an engineer who knows the target platform and can script file copies can often do it alone, but the work needs several skills at once: exporting objects and metadata from Cloud Storage, rebuilding access rules in the new platform, testing signed or public links, and operating the storage backend afterward. Supabase documents scripts in its community firebase-to-supabase repository that cover Storage files, and Appwrite's Migrations feature can import Firebase projects, though neither removes the need to verify results. Self-hosted Supabase is community-supported, and PocketBase is volunteer-developed, so ongoing support is your responsibility unless you contract it. DeployOpen implements, hardens and documents these migrations under a written, fixed scope.

How long does a Firebase Storage migration take?

The timeline depends on the number of files and bytes to copy, how many access rules and client code paths must change, how much testing the team requires, and whether the cutover can be staged. No researched figure for typical duration is available here, so ask the provider to state the duration and its assumptions in the written scope. Plan for a parallel period in which Cloud Storage and the new store both serve files, because cutover risk is highest when signed links, upload paths and thumbnail generation change at once. Request a dated plan that separates the copy, the rule rebuild, the test window and the cutover.

Is the Blaze plan requirement the only reason to move files off Firebase?

No. Cloud Storage for Firebase has required the pay-as-you-go Blaze plan since changes announced in September 2024, and that alone prompts many evaluations. Other common drivers include data location, since Firebase Authentication processes data only in the United States and a Cloud Firestore location cannot be changed after provisioning, and the desire to keep files, users and database rows in one platform. Some teams also want control over backups and retention. Before deciding, check which of these apply to your files, because moving storage alone may not fix a residency problem if authentication stays on Firebase.

How do we keep uploaded files inside the EU or another region?

Start by deciding where the files must live, then choose a store and host in that location. On self-hosted Supabase or Appwrite, the object store can be a local disk or an S3-compatible service you run or rent in an EU data center, so files, auth and database rows stay in the same environment. Supabase Cloud projects are hosted in one main region chosen from 17 AWS regions, which is set at creation, so confirm the region before you commit. Check every backup copy, log sink and CDN cache too, since residency rules often cover them. Ask the provider to document the data flow for each component.

What access rules must we rebuild for files?

Firebase Storage rules are written in its own rule language and tied to Firebase Auth, so each rule must be re-expressed in the target platform's model. Supabase Storage uses Postgres policies on storage objects, Appwrite uses permissions set on buckets and files, and PocketBase uses access rules on collections and file fields. Map each existing path pattern to a policy, then test read, write, delete and signed-link behavior with real user roles. Auth identities also need mapping because user IDs differ, so budget time for that work in the scope.

Should we choose PocketBase file fields for storing files?

PocketBase is a reasonable choice only for smaller apps with modest file volumes. It stores uploads in pb_data/storage on local disk by default and can switch to external S3-compatible storage from the dashboard. Its FAQ describes SQLite with vertical-only scaling on a single server, and the documentation says it is not yet recommended for production-critical applications before v1.0.0. For larger file estates, Supabase Storage or Appwrite Storage with a dedicated S3-compatible backend gives more room to grow. Confirm the scale you expect and test it before deciding.

What self-hosted file storage costs to run and who pays for it

Self-hosted file storage replaces a metered Cloud Storage bill with costs you pay to your own infrastructure provider and staff, so the first decision is which cost components you will own. The main recurring items are the servers or VMs that run the storage service (Supabase Storage with its imgproxy and database dependencies, Appwrite's Storage service inside its Docker or Helm stack, or PocketBase's single executable), the disk or object capacity behind them (local disk for PocketBase by default, or an S3-compatible store such as Garage or SeaweedFS), backups, monitoring, and the staff time to patch. Capacity cost grows with the volume of files and with replication you add for durability, while compute cost follows peak download and image transformation load. Ask your infrastructure provider to price each of these separately so you can see which line moves when your file volume grows.

Backups deserve the most careful line item. Supabase's self-hosting docs list managed backups and point-in-time recovery as unavailable when you self-host, so you must budget for your own backup tooling, its storage target and restore tests for both the Postgres metadata and the object store, since a file record without its bytes is a broken application. Appwrite's Helm chart docs say its built-in object storage runs a single replica without failover, which means production file data usually needs a replicated external store, another recurring cost. The Supabase changelog also flags one-way Storage database migrations that require a backup before updating, so staff time for each release should include a rehearsal on a copy.

Patching is the cost most often under-quoted. Self-hosted Supabase releases its Docker configuration as a bundle that pins specific Auth, PostgREST and Realtime versions, so each release means pulling and recreating services in your environment, and the 0.8.3 release flagged security fixes for Storage. Appwrite and PocketBase also ship frequent releases, and PocketBase warns of manual migration steps before v1.0.0. Support is community-based for self-hosted Supabase and volunteer-based for PocketBase, so a paid support contract or internal on-call rota is a cost you must add. For one-time work, the migration of files and the rebuild of access rules into Storage policies or Appwrite permissions is the largest item. Request a quote that separates the one-time migration and rules rewrite from the monthly run cost, names the storage capacity assumption, includes backup and restore testing, and states which upgrade windows and security patch response times are covered and which are not.

Keeping Firebase Auth or Firestore while storage moves

Most teams do not move storage, auth and data in one step. The four states below describe the hybrid setups that usually appear during a storage move, and each one changes where file metadata, access checks and tokens have to live. Pick the state that matches your current Firebase usage before you change any bucket or upload path.

Firebase Auth with self-hosted storage

Users still sign in through Firebase Authentication, but files sit on Supabase Storage, Appwrite Storage or PocketBase. Your storage layer must verify Firebase ID tokens or map them to a user record, and the bucket or file rules must check the same user identity. Confirm the token verification method with the storage product's docs, and plan how user IDs from Firebase map to the new store. Because Firebase Authentication processes data only in the United States, any user metadata you copy to the new store will sit outside the US unless you keep it in Firebase.

Firestore with Supabase Storage

Firestore documents keep their data, but the file references inside them point to paths in a new bucket. Store the object path, not a signed URL, so links can be regenerated after cutover. Check that every path written into a document has a matching object in the new store, and that deletes in one system trigger deletes in the other. Test a sample of documents end to end before you rewrite any production references.

Files on Firebase, new uploads elsewhere

Existing objects stay in Cloud Storage for Firebase while new uploads go to the new store. This keeps old file links working but leaves two places to search, back up and audit. Decide how a file's location is recorded, since a single document field may need a prefix or a bucket name to show which system holds it. Set a review point to decide when the old bucket is copied in full, and confirm with your team how long Blaze billing for the old bucket continues.

Full storage move with data residency checks

All objects, metadata and access rules move to the new store in one cutover window, with the new bucket in the region you chose. Cloud Storage for Firebase has required the Blaze plan since the changes announced in September 2024, so the cutover date sets when that billing stops. Before you copy anything, confirm the region of every destination bucket and of the database that holds file metadata, and document the result for your residency review.

What DeployOpen delivers for a storage replacement

DeployOpen delivers a storage replacement under a written, fixed scope agreed before work starts. The scope names the storage backend (Supabase Storage, Appwrite Storage or PocketBase file fields), the object store behind it (local disk or an S3-compatible store such as Garage or SeaweedFS), the buckets or collections in use, and the sign-off criteria for cutover. Scope, deliverables and timelines are set out in writing, so the reader can compare them against internal estimates before committing. Any timeline or fee is quoted from that written scope, not from a standard package.

The core deliverables are a rules inventory, a deployed storage stack, a migration runbook and a security test of access policies. The rules inventory lists every Firebase Storage security rule, the paths and file types each one covers, and the client code that depends on them, then maps each rule to its equivalent in the target platform. The deployed stack is installed inside the client's own cloud account, data center or air-gapped network, with secrets generated rather than copied from example files. The runbook covers export of objects from Cloud Storage, checksum verification after upload, the database backup to take before any one-way storage migration, and the rollback path. The security test checks that anonymous, cross-user and expired-session requests are refused on every rebuilt policy.

Optional retainers cover upgrades and continuous testing after cutover. Storage components release often, and some storage-related changes in the self-hosted Supabase Docker configuration flag security fixes, so the reader should agree in advance who applies updates, how they are tested and who owns patch windows. Continuous testing can repeat the access policy checks after each release. Before requesting a quote, confirm the file volumes, the number of user groups with different access, whether files are shared through public links, and which compliance evidence the organization needs. DeployOpen prepares systems, controls and evidence for compliance assessments, but independent auditors issue any audit report.

How DeployOpen scopes and delivers Firebase storage replacements

DeployOpen plans, implements, hardens and documents file storage replacements for Firebase projects inside the client's own infrastructure, whether that is Supabase Storage, Appwrite Storage or PocketBase file fields. Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

How we scope

  • Inventory every Cloud Storage bucket, its file volume, object paths and which client apps read or write them.
  • Map each existing security rule to the access model of the target platform and record the gaps.
  • Agree in writing which storage backend applies, such as local disk or an S3-compatible store, and where it runs.

How we build

  • Set up the chosen storage service in your environment with secrets generated and stored outside source control.
  • Copy file objects and paths from Cloud Storage, then verify checksums and object counts against the source.
  • Rebuild access rules as platform policies or file permissions, then test them with real user roles in a staging copy.

How we hand over

  • Document the architecture, bucket layout, access rules, backup procedure and the cutover and rollback steps.
  • Run a cutover rehearsal with your team and record the results as evidence for your own assessors.
  • Hand over runbooks for upgrades, since the storage components of these platforms change between releases.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, agreed separately from the initial scope.
  • Security testing of the storage endpoints and access rules can be scoped as a separate fixed engagement.
  • Confirm with DeployOpen during scoping which support hours, response paths and upgrade windows the retainer includes.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.