GeoParquet

GeoParquet is an ordinary Parquet file that has agreed on how to store geometry, so a reader can treat a table of features the same way analytics engines already treat any other large columnar dataset. That single idea is what makes it the vector companion to the cloud-optimized GeoTIFF: where a COG rearranges raster bytes so a reader can fetch just the window it needs, GeoParquet arranges vector features into columns so a reader can fetch just the fields and rows it needs. The features do not change — a parcel, a road, a labelled sample point is still the same record it was in a Shapefile or GeoJSON — but the layout changes, and with it what a large vector read costs. This note takes the engineering angle on why columnar storage matters for vector data, how GeoParquet encodes geometry and metadata, and where it fits alongside the other formats. It is not a library command tutorial; the durable knowledge is the reasoning, not any one tool’s API.

Why columnar storage changes vector reads

A traditional vector file is row-oriented: each feature’s geometry and all of its attributes are stored together, one record after another. To answer a question like “give me the population field for every county,” a reader still has to walk past every county’s full geometry and every other attribute along the way. Parquet turns this on its side. It stores each column contiguously — all the geometries in one place, all the population values in another, all the timestamps in a third — and it does two things that row layouts cannot. The first is column pruning: a query that needs three fields out of forty reads only those three columns off storage and never touches the rest. The second is predicate pushdown: Parquet keeps per-chunk statistics (the minimum and maximum value in each block of a column), so a reader filtering on year = 2024 or a bounding box can skip whole blocks whose statistics prove they cannot match, without decoding them. Both mechanisms mean the cost of a read scales with the size of the answer rather than the size of the dataset — the same economics shift that COGs bring to raster. For vector workloads that are often wide (many attributes) and selective (a small area or a single class at a time), that is the difference between scanning a continental table and reading the slice a question actually needs.

Geometry, coordinate systems, and metadata

Parquet on its own has no notion of geography, so GeoParquet is essentially a metadata contract layered on top. Geometry is stored in a dedicated column, most commonly as Well-Known Binary — a compact, widely understood encoding of points, lines, and polygons — so any engine that can read the bytes can reconstruct the shapes. File-level metadata then records the things a consumer must know to interpret those bytes correctly: which column holds the geometry, what geometry types it contains, the bounding box of the data, and, critically, the coordinate reference system the coordinates live in. That last point carries the same weight it does for raster: a longitude/latitude table and a projected table can look byte-similar and mean entirely different things, so the CRS must travel inside the file rather than in a sidecar that can drift or go missing. Because the metadata is self-describing, a reader can open a GeoParquet file cold — learn its geometry column, its CRS, and its extent — and start issuing correct spatial queries without any external configuration, which is exactly the property that lets these files sit in a shared data lake and be consumed by many different engines.

Partitioning and spatial indexing

A single Parquet file already prunes columns and skips blocks, but large vector archives go further by partitioning the data across many files along the axes queries filter on. Time is the natural first axis — a directory per year or per month means a query bounded to a date range never opens files outside it — and space is the second. Because geographic queries are usually windows, datasets are often partitioned by a spatial key: a coarse tile grid, an administrative region, or a spatial hash that keeps nearby features in the same file so a bounding-box read touches few partitions. Within each file, the per-chunk bounding statistics act as a lightweight spatial index, letting predicate pushdown skip row groups that fall outside the query window. The honest caveat is that partitioning is a design decision with a cost: too coarse and every query reads more than it needs; too fine and the dataset dissolves into thousands of tiny files whose per-file overhead and metadata coordination erase the benefit. Good partitioning matches the grain of the data to the grain of the expected time-series and spatial queries, the same judgement that tile-size choices demand for COGs.

Fitting into lakes, engines, and ML

GeoParquet’s real advantage is that it is Parquet, so it inherits an existing ecosystem rather than needing a bespoke one. It drops into the same object storage, data-lake table layouts, and query engines that already run over non-spatial Parquet, which means spatial data can join analytical workflows instead of living in a separate GIS silo. A distributed query engine can read partitions in parallel, push filters down to storage, and hand back only matching features — the vector analogue of reading COG windows in parallel across a distributed raster job. This matters especially for machine learning, where feature tables are wide, reused across many training runs, and filtered constantly by area, time, and class. Storing labelled samples and derived vector features as partitioned GeoParquet lets a ML pipeline read exactly the columns and spatial subset a given experiment needs, repeatedly and cheaply, without restaging the whole dataset each time. In each case the pattern is the one the cloud-native stack keeps returning to: keep the data in open, self-describing files in object storage, and read in place.

Where GeoParquet fits among the alternatives

GeoParquet is not a universal replacement, and placing it honestly means naming what each alternative still does better. GeoJSON is text — human-readable, trivially debuggable, and ideal for small payloads and web interchange — but it is row-oriented, verbose, and untenable at analytical scale; GeoParquet wins precisely when the data is too large to keep re-parsing as text. The Shapefile remains a stubborn interchange default, but its multi-file structure, attribute-name and size limits, and weak CRS story are exactly the constraints GeoParquet was designed to leave behind. A spatial database like PostGIS is the better tool when you need transactions, constant row-level updates, and a live query server with true spatial indexes; GeoParquet is a storage-and-analytics format, not a database, and it favours large append-mostly datasets read in bulk over records that change one at a time. Tiled vector formats such as vector tiles are built for rendering maps at zoom levels, a different job from analytical querying — they answer “what should this map tile show” rather than “which features match this filter.” The way to hold all of this is to remember what GeoParquet actually is: the columnar storage-and-access layer for vector data, arranged so the cost of a read matches the size of the question. Choose it when the workload is large, analytical, and read-heavy; reach for the others when their strengths are what the task needs; and the format lands where it belongs in the cloud-native stack.