Most spatial web platforms are the same three tiers: a database that understands geometry, a server that publishes it as standard map services, and a browser library that draws it. PostGIS, GeoServer, OpenLayers. The stack is unglamorous and it works.
What decides whether it performs is a handful of choices that are easy to get wrong early and expensive to change later.
Put the geometry in the database, not next to it
PostGIS is PostgreSQL with a geometry type and a spatial index. The index is the entire argument:
CREATE INDEX observations_geom_idx
ON observations
USING GIST (geom);
Without it, a bounding-box query is a sequential scan over every row. With it, the same query touches only the rows in view. On a few hundred thousand observation points that is the difference between a map that pans smoothly and one that does not.
Store a projection you can live with. Web mapping wants EPSG:3857; analysis usually wants EPSG:4326 or a local projected system. Reprojecting on every request is a cost you pay forever.
GeoServer reads the table directly
The temptation is to export data into a format GeoServer likes. Resist it. Point GeoServer at the PostGIS table and there is no export step, no scheduled job, and no second copy drifting out of sync with the first.
Two things to configure and then forget:
- Layer caching. GeoWebCache in front of tiled layers turns repeated tile requests into file reads. For any basemap-like layer this is the single biggest win available.
- Styling in SLD. Keeping cartography server-side means the same rules apply to the web map, a WMS client, and a printed export.
OpenLayers is the boring correct choice
It is heavier than the alternatives and its API is verbose. It also handles projections properly, speaks WMS and WFS natively, and does not assume you are building a consumer map with a commercial basemap underneath.
For a portal that has to render authoritative data with real coordinate systems, that trade is worth making.
The layer that decides everything
The question that determines the architecture is not which library to use. It is how much data has to reach the browser.
If the answer is "a few thousand features", send GeoJSON and let OpenLayers draw it. If it is "every observation in the country", the browser must never see the raw data — render server-side, tile it, and send images.
Getting this wrong is the most common failure in spatial web work. Everything else is configuration.