PostGIS & databases
Spatial data in Postgres: connecting, querying, and writing results back.
PostGIS is the right place for spatial data that several people share, that is larger than one person’s memory, or that needs an index somebody else maintains. Most of this topic is about the two seams: getting data in and out of Python, and getting the database to do the work rather than the client.
The recurring surprise is that a name in SQL is not an address. An unqualified table name is resolved through the search path, unquoted identifiers are folded to lower case, and permissions are two independent layers — so "relation does not exist" can genuinely mean "you may not look". The other recurring theme is arithmetic: keeping the indexed column bare so the index applies, and comparing rows in to rows out so a spatial join’s fan-out is noticed.
The concepts cover how geometry is stored and indexed; the how-to guides connect, query, write and upsert; and the fixes are the connection, permission and type errors that make up most of a first week with it.
🧭 Start with the concepts
The ideas the how-to guides below assume you already have.
- PostGIS Explained: When a Spatial Database Beats a Folder of Files
- How PostGIS Stores Geometry: SRID, EWKB and the Typed Column
- Spatial SQL or GeoPandas? Choosing Where the Work Happens
- PostGIS Spatial Indexes Explained: GiST and the Two-Phase Filter
- DuckDB Spatial Explained: A Spatial Database That Is Just a File
- DuckDB or PostGIS: Which One a Workflow Needs
⚙️ Then do the task
Step-by-step walkthroughs with code you can copy and adapt.
🔧 When it breaks
The errors this topic produces, with the cause explained rather than just the command.
Learning paths through this topic
A curated route rather than a list — the guides in the order that builds on itself.
Related topics
Subjects that keep coming up alongside this one, most overlap first.