Best Price Flights is a cross-platform mobile and web application that monitors flight prices several times a day — querying the world's leading flight search providers directly — and alerts users the moment fares drop. Rather than relying on occasional manual checks, the app works continuously in the background, so users can be confident they will always catch the best available price for their travel dates. When an alert arrives, they can act on it immediately — booking the flight straight from their smartphone or PC before the price changes again.
Creating a new search is equally effortless. Users can fill in the standard form, or simply describe what they are looking for in plain English using the built-in AI assistant: "two adults from Bristol to Rome, any time in May, under $300" — and the app will parse the request conversationally, resolve airports automatically, and set up the tracker. Once a search is active, Best Price Flights takes care of the rest.
The solution is built entirely on Microsoft .NET 10 and demonstrates a modern, cloud-native architecture spanning a MAUI Blazor Hybrid mobile app, two Blazor Server web applications, and an Azure Functions backend.
What Makes It Different
While similar services offer some form of price alerts, Best Price Flights takes a meaningfully different approach:
• Multi-provider aggregation — all providers' offers are queried simultaneously in a single tracker, giving a broader price picture than any single provider can offer
• Native mobile push notifications — alerts arrive instantly on the device, not just by email
• Configurable polling frequency — the operator controls how often price checks run, independent of any third-party schedule
• AI-assisted search creation — users can describe their trip in plain English and the built-in AI assistant resolves airports, extracts dates and passenger counts, and sets up the tracker conversationally — no other comparable service offers this
• Full price history — every price check is recorded, enabling trend analysis and not just a "price changed" flag
• Subscription tier system — a proper SaaS model with per-user quotas, provider allow-lists, and feature controls managed live from an admin panel
Solution Structure
The solution is composed of four projects sharing a common model library:
• BestPriceFlightsClient — a .NET MAUI Blazor Hybrid mobile application for end users (iOS, Android, Windows). Blazor components run inside a native MAUI shell, providing a fully native app experience with a shared Blazor UI codebase.
• BestPriceFlights.Admin — a Blazor Server web application for operators, providing tools to manage search polls, review user data, configure subscription tiers, and trigger manual price checks.
• BestPriceFlights.Functions — an Azure Functions v4 isolated worker app on .NET 10 that serves as the backend API for the mobile client, runs scheduled price polling, dispatches push and email notifications, and enforces subscription tier rules.
• BestPriceFlights.Shared — a class library shared across all projects, containing domain models, enums, and constants.
What the App Does
Users create flight search requests by specifying origin, destination, travel dates, and preferred search providers. The app periodically polls those providers for live prices and records the history. When a new price is lower than the previous best, the user receives a push notification and optionally an email alert.
Key capabilities include:
• One-way and roundtrip flight price tracking
• Multi-provider search (Kiwi, Google Flights, SkyScanner) with per-tier provider allow-lists
• Automatic price history recording and trend display
• Push notifications via Azure Notification Hubs (Firebase/APNs)
• Email price alerts via Gmail SMTP
• Subscription tier system (Free, Basic, Pro, Premium) with live Cosmos DB-backed configuration
• Quota enforcement — active search limits per tier, enforced at creation, reactivation, and load time
• Alternative flight exploration for one-way and roundtrip searches
• Admin panel for manual polling, tier editing, and user management
Technology and Design
The mobile client is a .NET MAUI Blazor Hybrid application targeting Android, iOS, and Windows from a single codebase. Blazor components are hosted inside a native MAUI BlazorWebView, giving the app full access to native device APIs while sharing the entire UI layer across platforms. Authentication is handled via Google OAuth using MAUI's WebAuthenticator, which stores the refresh token securely on the device and silently restores sessions on subsequent launches.
The backend is an Azure Functions v4 app running on the .NET 10 isolated worker model. All HTTP endpoints use AspNetCore integration (Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore), giving the Functions app full access to ASP.NET Core middleware — including a custom JWT validation middleware that validates Google ID tokens against Google's OIDC discovery endpoint using Microsoft.IdentityModel.Protocols.OpenIdConnect and System.IdentityModel.Tokens.Jwt. Every API call from the mobile client is authenticated and user-scoped this way without a separate identity server.
The admin application is a Blazor Server app with Interactive Server Components. It connects directly to Cosmos DB using the Microsoft.Azure.Cosmos SDK and provides a live admin interface with real-time state.
- Image: Main page on a large screen
- Image: Main page on a small screen
- Image: Last checked flights with booking links
Azure Cosmos DB — Configuration and Persistence
Azure Cosmos DB (via Microsoft.Azure.Functions.Worker.Extensions.CosmosDB and Microsoft.Azure.Cosmos) is the primary data store for the entire solution. It holds:
• UserProfiles — identity, subscription tier, and notification preferences
• SearchRequests — user-defined flight search configurations and active/paused/archived status
• PriceRecords — latest price results per search and provider
• PriceHistory — full historical price series for trend analysis
• PollSettings — configurable polling schedule and operational flags
• AlternativeFlights — cached results for alternative flight exploration
• TierDefinitions — live subscription tier configuration documents
TierDefinitions are treated as live configuration rather than hard-coded values. Each tier document (Free, Basic, Pro, Premium) stores quota limits, provider allow-lists, feature flags, pricing, and a subscriber-facing description. The admin app can edit and save these documents at any time, and the Functions backend reads them on every relevant API call — quota changes and provider restrictions take effect immediately without any redeployment.
On startup, the CosmosDbInitializer creates all required containers and seeds default TierDefinition documents for any tier not yet present in the database, preserving any existing admin edits.
Subscription Tier System and Quota Enforcement
The tier system controls what each user can do based on their subscription level:
• MaxSearchRequests — maximum number of simultaneously active search requests
• AvailableProviders — which flight providers are queried for one-way searches
• ReturnFlightProviders — which providers are queried for roundtrip searches
• SearchAlternativeFlights / SearchAlternativeFlightsRoundtrip — whether alternative flight exploration is available
• ShowAdvertisements — whether the app displays ads
• PriceUsd — subscription price
• Description — a plain-text description shown to the subscriber in their profile
Quota enforcement is applied at three points:
1. When saving a new search request (HTTP 402 Payment Required if quota is full)
2. When reactivating a paused search (same check, excluding the search being reactivated)
3. When the search list is loaded — any active searches exceeding the current tier quota are paused immediately, so a tier downgrade or admin quota reduction takes effect the next time the user opens the app
The background polling service applies the same quota enforcement during every scheduled poll run, pausing the oldest excess searches before processing.
Admin manual test polls bypass tier restrictions entirely, allowing operators to test any provider or search configuration regardless of the user's subscription tier.
Scheduled Price Polling
A timer-triggered Azure Function (FlightPricePollerTimerTrigger) runs on a configurable CRON schedule (stored in app settings as PollCronExpression). On each run, it:
1. Loads all active search requests across all users
2. Enforces per-user tier quotas, pausing excess searches
3. Auto-archives searches whose entire departure date window has passed
4. Queries the allowed flight providers for each search
5. Compares new prices against the stored price history
6. Persists new price records and raises price alerts for any drops
7. Dispatches push notifications and optional email alerts for each alert
Push Notifications and Email Alerts
Push notifications are delivered through Azure Notification Hubs (Microsoft.Azure.NotificationHubs), which abstracts delivery to both Firebase Cloud Messaging (Android) and Apple Push Notification Service (iOS). Device registration tokens are managed per user.
Email alerts are sent via Gmail SMTP using .NET's built-in SmtpClient. Email delivery is gated on the user's NotifyByEmail preference stored in their Cosmos profile — toggling the switch in the app's profile page immediately persists the preference, and no further alerts are sent until the user re-enables them.
Firebase Admin SDK (FirebaseAdmin) is used for token management and direct device messaging alongside Notification Hubs.
- Image: search results
- Image: search results detailed list
- Image: all alerts list
- Image
- Image
- Image
Application Pages — Mobile Client
Home / Dashboard
The main screen lists all the user's flight searches. Each card shows the route, date range, current best price, and active/paused/archived status. Searches that exceed the tier quota are automatically paused and shown clearly. The "New Roundtrip Search" button is hidden when the user's tier grants no roundtrip providers — no dead-end flows.
Search Creation (One-Way and Roundtrip)
Separate creation flows for one-way and roundtrip searches. On submission, the backend checks the active search quota and returns a user-friendly message if it is already full, rather than a generic error.
Search Results
Displays the latest price results from each provider as individual cards, showing price trends and the time of the last check. Provider cards are filtered to only show providers permitted by the user's tier. The "Explore more flights" option is hidden for tiers where alternative flight search is disabled. Paused searches can be resumed from this page, with the same quota check applied before reactivation.
User Profile
Shows the authenticated user's identity (name, email, avatar from Google), their current subscription tier, and the full live tier details loaded directly from the backend — quota, available providers, and the tier description. A notification preferences toggle controls email alerts. A "Change Subscription" button is present as a placeholder, displaying a notice that subscription changes are not yet available.
- Image: alternative flights select
- Image: alternative flights view
- Image: admin app tiers settings
- Image: admin app user settings
Admin Application
The Blazor Server admin app provides:
• Tier Settings — edit all four subscription tiers, including quotas, provider allow-lists, feature flags, pricing, and description text
• Poll Management — view and edit the polling schedule, trigger manual full polls or per-provider test polls for any user's search
• User and Search Browser — inspect user profiles, search requests, and price history
• Notification Testing — send test push notifications and email alerts to specific users
All admin poll triggers bypass tier-based provider restrictions, making it straightforward to diagnose issues across all providers regardless of a user's subscription.
Key Tools and NuGet Packages
Backend — Azure Functions (BestPriceFlights.Functions)
• Microsoft.Azure.Functions.Worker 2.51.0 — isolated worker host for .NET 10 Azure Functions
• Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.1.0 — full ASP.NET Core middleware pipeline in Functions
• Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.14.0 — Cosmos DB trigger and binding support
• Microsoft.Azure.Functions.Worker.Extensions.Timer 4.3.1 — CRON-scheduled timer triggers
• Microsoft.Azure.NotificationHubs 4.2.0 — push notification delivery via FCM and APNs
• Microsoft.ApplicationInsights.WorkerService 2.23.0 — telemetry and diagnostics
• Microsoft.Azure.Functions.Worker.ApplicationInsights 2.50.0 — Application Insights integration for the isolated worker
• FirebaseAdmin 3.1.0 — Firebase device token management and direct FCM messaging
• Microsoft.IdentityModel.Protocols.OpenIdConnect 8.17.0 — Google OIDC discovery for JWT validation
• System.IdentityModel.Tokens.Jwt 8.17.0 — JWT parsing and signature verification
Admin App (BestPriceFlights.Admin)
• Microsoft.Azure.Cosmos 3.58.0 — direct Cosmos DB access for the admin Blazor Server app
• Newtonsoft.Json 13.0.4 — JSON serialisation utilities
Mobile Client (BestPriceFlightsClient)
• Microsoft.Maui.Controls (MAUI) — cross-platform native shell for Android, iOS, and Windows
• Microsoft.AspNetCore.Components.WebView.Maui — Blazor Hybrid host inside MAUI
• Microsoft.AspNetCore.Components.Authorization 10.0.5 — authentication state and route protection in Blazor
• Microsoft.Extensions.AI 10.4.1 — unified AI abstraction layer
• Microsoft.Extensions.AI.OpenAI 10.4.1 — OpenAI/Azure OpenAI provider for the AI extensions
• Microsoft.Extensions.Http 10.0.5 — typed HttpClient factory for API communication
• Microsoft.Extensions.Configuration.Json 10.0.5 — embedded appsettings.json configuration
• Xamarin.Firebase.Messaging 125.0.1.2 (Android) — Firebase push notification registration on Android
Azure Services
• Azure Cosmos DB — document database for all application data and live tier configuration
• Azure Functions v4 — serverless compute for the API and background polling
• Azure Notification Hubs — cross-platform push notification delivery
• Azure Application Insights — monitoring, logging, and performance diagnostics
• Gmail SMTP — email delivery for price alerts
Technical Summary
Platform .NET 10
Mobile Client .NET MAUI Blazor Hybrid (Android, iOS, Windows)
Admin App Blazor Server, Interactive Server Components
Backend Azure Functions v4, Isolated Worker
Database Azure Cosmos DB (NoSQL, document model)
Authentication Google OAuth 2.0 + MAUI WebAuthenticator + custom JWT middleware
Notifications Azure Notification Hubs + Firebase Admin SDK + Gmail SMTP
Configuration Live Cosmos DB-backed tier definitions
Monitoring Azure Application Insights
Deployment Azure Function App (West Europe), Azure Blob Storage
Best Price Flights is a practical, fully cloud-integrated flight price tracking solution that showcases how .NET MAUI Blazor Hybrid, Azure Functions, and Cosmos DB can be combined to deliver a seamless cross-platform experience — with real-time data, flexible subscription control, and instant push notifications — all from a single, shared .NET 10 codebase.