A tactical field app lives or dies on its basemap. When the soldier holding the phone is in a valley with no cell signal, no satellite backhaul, and a battery that has to last the mission, the map has to already be on the device — every tile, every contour, every road, packed into a file that was loaded before the operator left the wire. The question of which container format holds that map is not a cosmetic one. It drives storage budgets, render performance, the tooling your pipeline needs, and whether the data drops straight into ATAK or needs a conversion step in the field. This is an engineering comparison of the three formats that matter: GeoPackage, MBTiles, and PMTiles.
1. the offline basemap problem
The defining constraint of a field app is the absence of backhaul. There is no tile server to call, no CDN, no live API. Everything the renderer will ever draw has to be resident on local storage before the device goes dark. That turns map delivery into a packaging problem: you need a single, copyable, verifiable artifact that holds an entire region's worth of map data and that a mobile renderer can query at speed off flash storage.
Storage is finite and contested. A rugged Android end-user device might allocate 16–64 GB to mission data, shared across imagery, elevation, full-motion video clips, and the basemap. A theater-wide raster basemap at usable zoom levels can run to tens of gigabytes on its own. So the container format is not just a wrapper — its compression behavior, its tile-pyramid structure, and its query cost directly decide how much map you can carry and how fast it paints.
2. MBTiles — the SQLite tile container
MBTiles is the format that made offline mapping ordinary. It is, at its core, a SQLite database with an agreed schema: a tiles table keyed by zoom level, column, and row, plus a metadata table of name/value pairs describing bounds, min/max zoom, format, and attribution. The genius is its simplicity — any platform with a SQLite library (which is every mobile platform) can open and query it with no special driver.
MBTiles holds either raster tiles (PNG, JPEG, WebP) or vector tiles (Mapbox Vector Tiles, gzip-compressed protobuf). Raster MBTiles is what most field operators have actually used: pre-rendered imagery or scanned topographic sheets, sliced into the standard Web Mercator tile pyramid and stuffed into the database. The metadata table's format field tells the client whether to expect png or pbf, and the TMS row-numbering convention (y-flipped relative to XYZ) is the one persistent gotcha that bites every new implementer once.
Its ubiquity is the headline. MBTiles is a de facto standard with a decade of tooling behind it, and it is the lingua franca of the open offline-mapping ecosystem. If you have to pick a format that something downstream will definitely understand, MBTiles is the safe bet.
3. PMTiles — the single-file cloud-optimized format
PMTiles, created by Brandon Liu, solves a problem MBTiles cannot: serving tiles directly from static storage with no database process. A PMTiles archive is a single file with a compact directory at the front and the tile data behind it, laid out so a client can fetch any individual tile with an HTTP range request. Put the file on a plain object store or a flash card and the client reads the directory once, then byte-range-requests only the tiles it needs — no tile server, no SQLite process, no unpacking.
For a field app this has two distinct payoffs. On a connected staging network, a PMTiles archive on a static bucket replaces an entire tile-server stack, which is one fewer thing to deploy and accredit. On the device, the same single-file, append-only layout copies and checksums cleanly and is friendly to mmap-style reads. The format's clustered directory keeps the index small even for planet-scale archives, so the per-tile lookup stays cheap. The trade-offs around MBTiles and PMTiles offline maps come down to whether your renderer speaks the range-request access pattern natively or expects a SQLite handle.
Key insight: MBTiles, PMTiles, and tiled GeoPackage all encode the exact same Web Mercator tile pyramid — the same PNG or vector-tile bytes. The format war is not about the tiles; it is about the index in front of them. Choose the index that matches how your renderer reads storage: SQLite query, HTTP range, or OGC feature access. The pixels are identical.
4. GeoPackage — the OGC standard
GeoPackage (GPKG) is the only one of the three that is a formal open standard, published by the Open Geospatial Consortium and adopted as a US National Geospatial-Intelligence Agency and NATO-relevant container. Like MBTiles it is built on SQLite, but it is far more ambitious: a single GeoPackage file can hold raster tile pyramids, vector feature tables with full geometry and attributes, spatial indexes (R-tree), and the metadata to describe all of it. One file can be both your basemap and your vector overlay — friendly-force tracks, control measures, named areas of interest — in one queryable, editable database.
That breadth is the reason GeoPackage dominates in the formal defense-geospatial world. When a geospatial cell ships a mission data package, GeoPackage lets imagery tiles and the attributed feature data travel together in one accountable artifact with a documented schema the receiving system is contractually required to read. The cost is that GeoPackage is heavier to produce and that its full feature model is more than a pure basemap needs — you are carrying a standard built for editable GIS data, not just a tile cache.
5. size and performance trade-offs
Format choice changes file size less than people expect, because the dominant cost is the tile bytes, and those are largely the same across containers. The real levers are upstream: tile format (WebP beats PNG by 25–35% at equal quality), zoom-level cutoff, and whether you serve vector or raster.
Vector tiles are the big win. A raster basemap of a country at zoom 0–16 can be 20–40 GB; the equivalent vector-tile set, where geometry is encoded once and styled at render time, routinely lands at 1–3 GB for the same coverage. Vector also lets the device restyle on the fly — day/night palettes, mission-specific layer toggles — without re-rendering tiles. The cost is GPU and CPU at draw time: the device assembles the picture per frame instead of blitting a pre-baked image, which is exactly the kind of real-time map rendering budget you have to profile on the actual target hardware, not a developer laptop.
On query cost, the three are close in practice. SQLite-backed MBTiles and GeoPackage resolve a tile with an indexed primary-key lookup — microseconds off warm cache. PMTiles resolves through its in-file directory, which is one or two reads, also negligible once the root directory is cached. None of these is the bottleneck; storage I/O and decode/render are. The honest engineering conclusion: pick the format for tooling and integration fit, then spend your performance effort on tile format, zoom budget, and the renderer.
6. ATAK/TAK and field-app support
For the TAK ecosystem the answer is concrete. ATAK reads MBTiles and GeoPackage natively as basemap sources — drop the file in the right directory or import it through the package manager and it appears as a selectable map layer. Raster MBTiles is the most battle-tested path and the one most operators reach for. GeoPackage is the right choice when you need the imagery and attributed vector features in one importable mission package, which is the standard way formal data products reach the client.
PMTiles is the newer arrival. It is increasingly supported through plugins and in modern MapLibre-based clients, but it is not yet the default native basemap import across every TAK build, so verify the specific client version before you standardize on it for a fielded program. The pragmatic workflow many teams run: author and store in PMTiles for its single-file serving advantages, then export to MBTiles or GeoPackage for the final device package when the target client demands it.
7. tooling
The conversion pipeline is where engineering hours actually go. For vector tiles, tippecanoe — originally from Mapbox, now maintained by Felt — is the workhorse: it turns GeoJSON or other vector sources into an optimized MBTiles or PMTiles vector-tile set, handling feature dropping, coalescing, and zoom-level generalization so dense data stays renderable at low zoom. It is the single most important tool in an offline-vector pipeline.
For everything else, GDAL is the universal adapter. Its raster and vector utilities convert between formats, build tile pyramids, and read or write GeoPackage, MBTiles, and (in current releases) PMTiles. ogr2ogr moves vector features into GeoPackage feature tables; gdal_translate and gdaladdo build raster GeoPackage tile pyramids; gdal2tiles slices imagery into the standard pyramid. A typical production pipeline chains source data → GDAL or tippecanoe → container → integrity check → mission data package, scripted and reproducible so the same region rebuilds byte-for-byte. The PMTiles command-line tool rounds it out, converting MBTiles to PMTiles and inspecting archive directories.
8. choosing for a field app
The decision collapses to three questions. First, raster or vector? If you can author and style vector tiles end to end, do it — the 10x size reduction and on-device restyling are decisive for storage-constrained devices. Fall back to raster only when the source is imagery or scanned sheets that have no vector equivalent.
Second, single-file serving or feature richness? If you need imagery plus attributed, editable vector features in one accountable artifact — the formal mission-data-package case — GeoPackage is the answer, and its OGC-standard status is what gets it accepted across a coalition. If you are shipping a pure basemap and want the lightest serving story, PMTiles' single-file, server-less model wins.
Third, what does the client read today? For TAK programs fielding now, raster or vector MBTiles for the basemap and GeoPackage for combined imagery-plus-features packages is the pragmatic default — both import natively, both are battle-tested. Adopt PMTiles where your renderer already speaks range requests and you control the client version. Whatever you choose, keep the format out of your core domain: store the canonical map data once, and treat MBTiles, PMTiles, and GeoPackage as interchangeable export targets from one reproducible pipeline. The container is a packaging decision, not an architecture you should be locked into.