Mapbox vs Google Maps in Flutter (and Where flutter_map Fits)
Mapbox vs Google Maps in Flutter, plus flutter_map with OpenStreetMap: styling, offline maps, markers at scale, pricing models and keeping your API keys locked down.

“We need a map” is one of the shortest lines in any app brief, and it hides one of the longer decisions. Which map SDK you choose affects how the app looks, whether it works offline, how it copes with thousands of markers and what the monthly bill looks like once real users arrive.
At Mascopia I built live tracking on Google Maps, so that’s the SDK I know best in production. But I don’t reach for it automatically. Here’s how the three main Flutter options compare and how I choose between them.
The three contenders
google_maps_flutter is the official plugin from the Flutter team. It wraps the native Google Maps SDKs for Android and iOS. You get Google’s map data, a familiar look, and an API that feels like Flutter: a GoogleMap widget, a Set<Marker>, a controller for moving the camera.
mapbox_maps_flutter is Mapbox’s official plugin. It wraps the Mapbox Maps SDK, which renders vector tiles on the device and is built around fully customizable styles. The API stays closer to the native SDK than Google’s plugin does. You work with styles, sources, layers and annotation managers rather than a simple set of marker widgets.
flutter_map is a community package that draws the map in Flutter itself. It isn’t tied to a vendor. You point it at any tile server: OpenStreetMap, a commercial tile provider or your own. Markers are ordinary Flutter widgets, which makes custom designs very easy.
Side by side
| google_maps_flutter | mapbox_maps_flutter | flutter_map | |
|---|---|---|---|
| Rendering | Native Google SDK in a platform view | Native Mapbox SDK, vector tiles | Pure Flutter, raster or vector tiles via plugins |
| Styling | JSON styles or cloud-based styling via map IDs | Full control with Mapbox Studio styles | Whatever your tile provider offers |
| Offline maps | No supported download API in the plugin | First-class offline regions | Possible with caching plugins and the right tile license |
| Many markers | Built-in clustering in recent versions | Clustering on GeoJSON sources | Community clustering plugin |
| Pricing model | Pay per use of Google Maps Platform APIs | Mobile SDK priced by monthly active users | Free library; you pay your tile provider |
| Best for | Familiar look, Places and routing | Branded maps, offline, data-heavy maps | Custom UI, vendor independence |
Styling: how much does the map need to look like your app?
Google Maps can be restyled more than people think. You can hide points of interest, recolor roads and water, and switch to a dark theme with a JSON style, or manage styles from the Cloud Console using map IDs.
Mapbox goes much further. You design the whole map in Mapbox Studio (fonts, which layers exist, how they look at each zoom level) and load it by style URL. If the map is the product, as in a travel app, an outdoor app or a data visualization, that control is the main reason to pick Mapbox.
flutter_map’s look depends on your tile source. Some providers offer several ready-made styles. Since markers and overlays are plain widgets, your own UI on top of the map is the easiest to customize of the three.
Offline: does the map have to work without signal?
This question settles more decisions than any other. If users need maps in places with poor coverage, such as field workers, hikers or delivery drivers in rural areas, Google Maps is weak here. The native SDK caches tiles it has already shown, but the Flutter plugin gives you no supported way to download a region in advance.
Mapbox handles offline as a core feature. You define a region and zoom range and download its tiles and style into a tile store, and the map uses them without a connection. Check how your plan counts offline downloads before you promise “download the whole country”.
flutter_map can work offline using tile caching plugins or bundled tile files, but the tile license matters more than the code. More on that below.
If the rest of the app must work without a connection too, see offline-first Flutter apps.
Markers at scale
Ten markers work anywhere. Thousands need a plan.
- Cluster. Group nearby markers into one bubble with a count, and split them apart as the user zooms in. Recent versions of google_maps_flutter support clustering natively. Mapbox does it on the data source, which handles large datasets well because the native SDK does the work. flutter_map relies on a community clustering plugin.
- Only load what’s visible. Query your backend by the camera’s visible bounds, with a short debounce while the user pans. Don’t download every location in the database on app start.
- Watch custom marker images. On Google Maps, every marker icon is a bitmap. Generating a unique image per marker (avatars, prices) gets expensive. Cache icons by content instead of regenerating them on every rebuild.
- Move markers smoothly. For live tracking, animating a marker between position updates matters more than the update rate. I covered that, along with the rest of the tracking setup, in live location tracking with Google Maps.
Pricing models, not prices
I won’t quote numbers, because all of these vendors change their pricing and free tiers. What matters is what you pay for, because that decides how your bill grows:
- Google Maps Platform bills per use of individual APIs. The map display is often the smallest part. Geocoding, Places autocomplete, Directions and distance calculations are separate products with their own prices, and a chatty search box can generate a lot of requests. Debounce autocomplete and use session tokens where the API supports them.
- Mapbox prices its mobile SDKs mainly by monthly active users, with separate pricing for its search, geocoding and navigation APIs. That’s predictable if you know your user numbers.
- flutter_map is free, but the tiles aren’t. You pay a tile provider (usually by tile requests) or run your own tile server.
Before choosing, I estimate the API calls for each user session (map opens, searches, route requests) and run that through each vendor’s current calculator.
OpenStreetMap tiles are not a free CDN
This mistake comes up again and again with flutter_map. The quick-start examples use the public tile.openstreetmap.org servers, and many apps ship to production still using them.
Don’t. The OpenStreetMap Foundation runs those servers on donated resources, and its tile usage policy forbids heavy use. It also requires a proper user agent and attribution, and apps that break the rules can be blocked. Use a commercial tile provider built on OpenStreetMap data, or host your own tiles. Whichever source you use, set flutter_map’s user agent package name and show the required attribution on the map. The OpenStreetMap data is open. The free tile servers are not meant to carry your app’s traffic.
Lock down your keys
Every option here ships some kind of key or token inside the app, and anything in the app can be extracted. So the goal is to make an extracted key useless elsewhere:
- Google: use separate keys for Android and iOS. Restrict the Android key to your package name and signing certificate fingerprint, and the iOS key to your bundle ID. Also restrict each key to only the APIs it needs. A Maps SDK key shouldn’t be able to call Geocoding.
- Mapbox: ship only public tokens with the minimum scopes. Secret tokens belong in CI or on your server, never in the app.
- All: set budget alerts and quotas in the vendor console. A leaked key with no quota is a billing problem waiting to happen.
Server-side calls such as geocoding in bulk should go through your backend with a separate, server-restricted key. My mobile app security checklist covers the wider picture.
So which one do I pick?
My rough decision order:
- Need real offline maps? Mapbox, or flutter_map with a tile provider whose license allows offline use.
- Need Google Places search, Google-quality routing or the familiar Google look? Google Maps.
- Map is a core brand surface, or you’re showing lots of data on it? Mapbox.
- Want vendor independence or very custom marker UI, and the map is a supporting feature? flutter_map with a commercial tile provider.
When none of those apply, I default to Google Maps. Users know it, and the Flutter team maintains the plugin.
Takeaways
- google_maps_flutter is the safe default. Mapbox wins on styling and offline. flutter_map wins on flexibility and vendor independence.
- Ask about offline first. It removes options faster than any other requirement.
- Plan for many markers from the start: clustering, loading by visible bounds and cached marker icons.
- Compare pricing models against an estimate of real usage, not against the free tier.
- Never use the public OpenStreetMap tile servers in production. Use a tile provider and show attribution.
- Restrict every key by platform, app identity and API, and set quotas.
If you’re weighing map options for a location-based app, send me the brief and I’ll tell you which way I’d go.
Comments
Questions, corrections or your own experience — leave a comment below (GitHub sign-in).