← All articles
GIS 2 Jul 2026 · 9 min

PostGIS Setup for Network & Infrastructure Data: Beyond CREATE EXTENSION

Standing PostGIS up as the operational datastore for asset and network data — schema, roles, the ArcGIS curve trap, and where it beats a geodatabase.

Most “PostGIS setup” guides stop at CREATE EXTENSION postgis;. That line is real, and it matters, but it’s the least interesting decision you’ll make. The official docs and the cloud vendors already own the install-and-enable story, and they do it better than anyone else can. This piece assumes you can install software.

The harder question is the one nobody writes about: how do you stand PostGIS up as the operational datastore for asset and network data — the system-of-record that QGIS, ArcGIS, a web portal, and a pile of Python jobs all read from and write to without corrupting each other? That’s a database problem, not a GIS problem, and it’s where infrastructure teams get hurt.

Install and enable — briefly

You need PostgreSQL, then the PostGIS extension enabled in the database you’ll use.

CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;   -- only if you'll use the topology model

Run SELECT postgis_full_version(); to confirm the GEOS, PROJ, and GDAL versions came along for the ride — those underlying libraries dictate what your spatial functions and projections can actually do.

That’s the whole install section, on purpose. If you’re on RDS or another managed PostgreSQL, the provider’s docs cover the platform specifics (parameter groups, allowed extensions, connection limits) far better than a general article can. On self-hosted, follow postgis.net. Read those, then come back — the rest of this is about what you build on top.

PostGIS as an operational datastore

An operational datastore for network infrastructure has a different shape from a scratch database you loaded a shapefile into to make one map. It has concurrent writers, long-lived integrations, and a schema that people depend on not changing under them. Three things earn their keep early.

Schema separation. Don’t dump everything in public. Split by concern — for example a network schema for the live asset model, a staging schema for inbound data that hasn’t passed validation, and a ref schema for reference layers (boundaries, cadastre, imagery footprints). This makes permissions tractable and keeps a migration import from touching production tables by accident.

Explicit geometry typing. A geometry column with no type or SRID constraint accepts anything, and eventually something wrong lands in it. Constrain it:

CREATE TABLE network.duct (
  id        bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  route_id  bigint NOT NULL,
  geom      geometry(LineStringZ, 27700) NOT NULL
);

Fix the geometry type and the SRID at the column. For UK fibre work that’s usually EPSG:27700 (British National Grid); pick the projected system your survey and design data actually use, not WGS84 (4326), which is fine for storage and web tiles but wrong for anything measured in metres. Mixing SRIDs across tables that need to be spatially joined is a slow, recurring tax — standardise once.

Roles, not one superuser. The failure mode is everyone connecting as the database owner. Define roles by function and grant against schemas:

CREATE ROLE gis_read;
CREATE ROLE gis_edit;
GRANT USAGE ON SCHEMA network TO gis_read, gis_edit;
GRANT SELECT ON ALL TABLES IN SCHEMA network TO gis_read;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA network TO gis_edit;

A read-only role for the web portal and analysts, an edit role for the design team, admin kept separate. This is the same discipline you’d apply to any production PostgreSQL database — the fact that the payload is geometry changes nothing.

Connecting QGIS and ArcGIS — and the curve trap

QGIS talks to PostGIS natively and well. Add a PostGIS connection, browse schemas, load layers, edit, done. QGIS understands PostGIS geometry directly because both sit on the same open stack (GEOS/GDAL). For a QGIS-and-PostGIS shop, there’s little to warn you about beyond the usual advice: filter large layers, and don’t drag a two-million-row table onto the canvas unfiltered.

ArcGIS is where it gets sharp. ArcGIS can consume PostGIS in two different ways, and the distinction is the single most common way infrastructure teams damage their data.

The first way is native PostGIS geometry — ArcGIS reads the standard geometry column that everything else reads. The second is registering the database as an enterprise geodatabase (adding Esri’s sde repository), after which ArcGIS prefers its own storage type. The problem lives in how ArcGIS represents true curves.

ArcGIS supports circular arcs and Bézier curves as first-class geometry. PostGIS’s core types are largely linear. To round-trip curves through PostGIS, ArcGIS stores the curve definition in a separate binary column that other PostGIS clients can’t interpret. So QGIS, GeoServer, or your Python job sees the linear approximation in the standard geometry column — not the curve ArcGIS drew. Practitioners on the Esri community forums describe exactly this: the extra binary column defeats the point of using native PostGIS geometry, because the geometry the rest of your stack reads is not the geometry ArcGIS authored.

The common workaround teams settle on is blunt: convert curves to straight-line segments (densify the arcs) so there’s a single, honest geometry every client reads the same way. You trade true-curve fidelity for interoperability. For most fibre and utility asset data — ducts, cables, service points — segmented geometry is perfectly acceptable, and a consistent read across every tool is worth more than a mathematically exact arc that only ArcGIS can see.

The trap is doing this accidentally, mid-project, and not noticing until a downstream client reports “wrong” geometry. Decide the curve policy up front. This is the same class of silent degradation that bites during platform moves — we cover the full set in Challenges in GIS Data Migration.

The practical rule: if ArcGIS is a first-class editor of your PostGIS data, either standardise on segmented geometry everywhere, or register a proper enterprise geodatabase and accept that non-Esri clients read an approximation. Don’t half-commit.

PostGIS vs file or enterprise geodatabase

The decision splits three ways, and it’s less about features than about who operates the thing.

File geodatabase is single-writer, file-based storage. It’s fine for a lone analyst, a data hand-off, or an offline package. It is not an operational datastore — concurrent editing isn’t its job, and treating it as a shared network drive for a team ends in lock contention and corruption. If more than one person needs to edit at once, it’s already the wrong tool.

Enterprise geodatabase is Esri’s multi-user model layered on a real RDBMS — and PostgreSQL/PostGIS is one of the supported backends, alongside SQL Server and Oracle. You get versioning (traditional or branch), the ArcGIS connectivity model, and Utility Network. The cost is that you’re inside the Esri operational envelope: licensing, the sde repository, service-based editing for branch versioning, and maintenance chores like compress and lock management. If your organisation already runs ArcGIS Enterprise and needs Utility Network, this is the road, and the operational detail deserves its own treatment — see Deploying and Maintaining a Multiuser Geodatabase.

Plain PostGIS — PostgreSQL with the extension, no sde layer — is the open operational datastore. Concurrent multi-user editing through PostgreSQL’s own MVCC, clean integration with web stacks and ETL because it’s just PostgreSQL, no per-seat GIS licensing on the database itself, and full SQL access to your spatial data. QGIS, GeoServer, Mapbox tooling, and any language with a Postgres driver all read it directly.

The honest decision rule: if the ArcGIS/Utility Network stack is your system-of-record, go enterprise geodatabase on PostgreSQL and live inside that envelope. If you want an open, integration-friendly datastore that a web portal and mixed toolchain sit on — and ArcGIS is a client rather than the centre — plain PostGIS wins. The mistake is running plain PostGIS and then bolting ArcGIS on as a heavy editor without deciding the curve and geometry-ownership question above.

Indexing and performance for large layers

Spatial performance on PostGIS comes down to two indexes and one honest distinction.

GIST on the geometry column is non-negotiable for any layer you query spatially:

CREATE INDEX duct_geom_idx ON network.duct USING GIST (geom);

Without it, every bounding-box or intersection query scans the whole table. With it, PostGIS uses the R-tree-over-GiST structure to prune to candidate features fast. Add it when you create the table, not after the queries are already slow — reactive indexing costs you an outage window to build on a large table.

BTREE on the attributes you filter and join on — status, route id, install date, whatever your queries actually key off. Spatial and attribute filters combine, and a query that filters “ducts in this tile installed after 2024” wants both a GIST index for the tile and a BTREE index for the date.

Then run ANALYZE (or let autovacuum do it) so the planner has current statistics, and check real queries with EXPLAIN (ANALYZE, BUFFERS). If the planner isn’t using your GIST index, something’s off — often a SRID mismatch forcing a reprojection, or a function wrapped around the column that defeats the index.

Now the honest distinction, because it’s where teams misdiagnose. On large polygon layers — think a couple of million records — practitioners report editing and query slowness even with GIST and BTREE indexes correctly in place. The reflex is to blame PostgreSQL. Often it isn’t the database. When the layer is consumed through an ArcGIS feature service, the bottleneck reported on the Esri forums is the service throughput — serialisation, the REST layer, the map/feature-service tier — not the PostgreSQL query underneath. A query that returns in tens of milliseconds against the database directly can feel slow through a feature service that’s paging and drawing millions of features.

We’re relaying that as a practitioner pattern, not a benchmarked law — but the diagnostic discipline it implies is sound. Before you tune PostgreSQL, measure where the time actually goes. Run the query directly against the database with EXPLAIN (ANALYZE, BUFFERS). If the database is fast and the map is slow, the fix is in the service tier or the client — generalisation, tiling, scale-dependent rendering, pagination — not in another index on a table that’s already indexed correctly. Tuning the wrong layer is how weeks disappear.

Where this leaves you

PostGIS setup for infrastructure data is 5% CREATE EXTENSION and 95% the decisions after it: schema separation, constrained geometry types and SRIDs, real roles, a deliberate curve policy the moment ArcGIS touches the data, the geodatabase-vs-plain-PostGIS call, and indexes built up front with a clear head about whether slowness lives in the database or the service in front of it. Get those right and PostGIS is a durable operational datastore for network and asset data. Skip them and you’ve built a very capable database that quietly degrades your geometry and blames itself for the map being slow.


Related reading


LayerSpec provides PostGIS setup and schema design for fibre, utility, and infrastructure teams — operational datastores built to be read by every tool in your stack, not just one.