Migrating from REST and MongoDB to Firebase
Maintaining a production mobile application over many years creates a challenge that almost every software team eventually faces: the technology that made sense when the application was originally built may no longer be the best architecture for supporting it today.
Blue Otter recently undertook a major modernization project for an established mobile application serving the wine and hospitality industry. The application provides users with access to wineries, businesses, events, promotions, maps, personalized content, and other information through native iOS and Android experiences.
Rather than rebuilding the application from scratch, our goal was to modernize its underlying infrastructure while preserving the functionality users and administrators already depended on.
The project involved migrating a REST API and MongoDB-based backend to Google Firebase, updating authentication and application services, restructuring how the mobile application receives data, migrating existing content, and establishing a more sustainable process for testing, deployment, monitoring, and ongoing maintenance.
The Challenge: Modernizing an Existing Production Application
The existing application relied on a traditional architecture where the mobile app communicated with a REST API, which in turn communicated with a MongoDB database.
Over time, that architecture had grown to include more than 50 API endpoints and 46 data models, along with separate systems for authentication, caching, file storage, application data, and other services.
That created several long-term maintenance considerations.
Data changes traveled through an API layer before reaching users. Offline functionality depended on a custom caching strategy. Multiple infrastructure components had to remain operational and compatible with one another. Changes to the backend could also require corresponding changes to API endpoints and the mobile application.
Our objective wasn’t simply to replace MongoDB with another database. We wanted to simplify the application’s overall architecture.
Moving to a Unified Firebase Architecture
We designed a new backend around Google’s Firebase platform, with Cloud Firestore becoming the primary application database.
This allowed several previously separate pieces of infrastructure to move into a common ecosystem:
- Cloud Firestore for application data
- Firebase Authentication for user authentication
- Firebase Storage for files and application assets
- Cloud Functions for server-side processing and business logic
- Firebase services for application analytics and notifications
One of the biggest architectural changes was eliminating the need for the mobile application to route every data request through a traditional REST API.
Where appropriate, the application can communicate directly with Firestore while Firebase Security Rules and backend functions provide the necessary controls around data access and business logic.
This reduces infrastructure complexity while creating a foundation that can scale as application usage grows.
Designing the Firestore Data Model
Moving from MongoDB and a REST API to Firestore isn’t simply a matter of copying database records.
Firestore’s document-oriented architecture requires careful consideration of collections, document structure, relationships, permissions, and query patterns.
Before migrating production data, we mapped the application’s 46 existing data models into a new Firestore architecture.
The process included defining collection and document structures, designing Firebase Security Rules, evaluating authentication requirements, and establishing separate staging and production Firebase environments.
We also accounted for the different types of content managed by the application, including businesses, events, promotions, editorial content, user accounts, preferences, notifications, interactions, and other application-specific data.
Replacing 50+ API Endpoints
A significant portion of the project involved replacing functionality previously handled through more than 50 REST API endpoints.
Rather than performing a one-for-one API rewrite, we evaluated how each function should operate within Firebase.
Standard data operations could move directly to Firestore repositories, while processes requiring trusted server-side execution could be implemented through Cloud Functions.
The application’s repository layer was rebuilt around Firestore, and file uploads were transitioned to Firebase Storage.
Complex operations that still required backend processing remained server-side rather than being pushed into the client application.
This approach allowed us to simplify the architecture without sacrificing the separation between client functionality and protected business logic.
Moving from Requests to Real-Time Data
One of the most valuable improvements was changing how the application receives updated information.
The previous architecture largely followed a request-and-response model. The application requested data from the API, received a response, cached it, and refreshed it again later.
Firestore provides real-time data listeners.
We updated the Flutter application’s state-management layer to support stream-based data rather than relying exclusively on future-based API requests.
For users, this means information such as winery profiles, events, promotions, and other application content can update automatically as the underlying data changes.
It also reduces the need for users to manually refresh screens to retrieve updated information.
Improving Offline Support
Offline use was another important consideration.
Mobile applications serving tourism and hospitality users cannot assume that every user will always have a fast, reliable connection. Users may be traveling, inside buildings with poor reception, or moving through rural areas where cellular service is inconsistent.
The previous application relied on a custom caching approach to maintain data locally.
Firestore provides native offline persistence and synchronization capabilities. Moving the application to Firestore allowed us to replace much of that custom caching architecture with functionality supported directly by the platform.
This creates a cleaner implementation while improving the application’s ability to work with intermittent connectivity.
Migrating Existing Data
A production migration has to preserve more than application code.
Existing database records and application assets needed to move into the new environment without disrupting the application.
We developed migration tooling to transfer data from MongoDB into Firestore and migrate applicable file assets into Firebase Storage.
Data integrity validation was incorporated into the process so migrated records could be cross-referenced against the original data before production deployment.
This was especially important because the application already contained years of real-world business and user data.
Testing Across iOS and Android
Modernizing the backend of an existing application affects nearly every part of the system, even when the visible user interface changes very little.
Testing therefore became a major part of the project.
Our QA process included repository-level testing, integration testing, end-to-end application flows, performance testing, staging validation, and User Acceptance Testing.
The application was distributed to testers on both iOS and Android, allowing stakeholders to validate real-world functionality before production release.
During UAT, we worked through issues involving map behavior, location controls, business profiles, data synchronization, filtering, events, test data, contact actions, and differences between staging and production content.
Some reported issues were application defects. Others were expected characteristics of the staging environment or existing data. Distinguishing between those categories is an important part of managing a production software release.
Separating Staging from Production
A reliable release process requires a safe place to test.
The project uses dedicated staging and production environments so new functionality and migrated data can be evaluated without immediately affecting production users.
Staging can contain test businesses, certifications, sample records, and other QA-specific content that should never appear in the live application.
This separation gives developers and stakeholders the ability to validate functionality, reproduce issues, and approve releases before changes reach the public.
Planning for Long-Term Maintenance
Launching a mobile application is only part of the lifecycle.
Apple, Google, Flutter, Firebase, operating systems, third-party libraries, and mobile devices all continue changing after an application is released.
For that reason, we also established an ongoing maintenance approach covering the mobile application and its Firebase infrastructure.
That includes proactive monitoring, reviewing platform and dependency changes, addressing critical application or infrastructure issues, and evaluating required iOS, Android, Flutter, and Firebase updates.
Updates aren’t automatically pushed simply because a new framework version becomes available. Changes are reviewed first so their impact can be understood and tested before deployment.
This provides a more controlled approach to maintaining a production application.
The Result: A More Sustainable Mobile Platform
The most important outcome of this project isn’t simply that one database was replaced with another.
The application moved from a collection of independently maintained backend components toward a more unified cloud architecture.
The modernization provides a foundation for:
- Real-time content synchronization
- Native offline data support
- Reduced dependency on custom API infrastructure
- Centralized authentication, database, storage, and server-side services
- Easier staging and production management
- Scalable cloud infrastructure
- More structured QA and release processes
- Ongoing monitoring and maintenance
Just as importantly, the migration was designed around an existing production application rather than a greenfield build.
That distinction matters.
Rebuilding a new application gives developers freedom to choose an architecture without worrying about what came before. Modernizing an established application requires understanding existing code, data, infrastructure, business rules, integrations, users, and operational processes—and then changing the underlying technology without unnecessarily disrupting them.
Need to Modernize an Existing Application?
Blue Otter works with organizations that have software already in production but need help moving it forward.
That can include legacy backend migrations, Firebase architecture, Flutter development, API modernization, cloud infrastructure, mobile application maintenance, iOS and Android deployment, QA, and taking over applications originally developed by another team.
You don’t always need to rebuild an application from scratch.
Sometimes the better solution is understanding what already works, identifying what no longer scales, and carefully modernizing the architecture underneath it.
