Building a Production-Ready PostGIS Environment on PostgreSQL 18

PostGIS extends PostgreSQL with powerful spatial capabilities, enabling you to store, query, and analyze geographic data. It is the foundation for many Geographic Information Systems (GIS) used by municipalities, utility companies, logistics providers, and public authorities. In this article, we build a production-ready PostGIS environment that will serve as the basis for future articles covering performance tuning, indexing, maintenance, monitoring, backup strategies, and high availability.

Since PostgreSQL 18 is already installed, as described in my previous article, we’ll focus on installing PostGIS, creating a spatial database, and loading a realistic dataset that can be used throughout this blog series.

Installing PostGIS

On RHEL 10, install the PostGIS packages using DNF as root:

# verify that the PGDG repositories are available
dnf repolist | grep pgdg
# enable the EPEL repository
subscription-manager repos --enable "codeready-builder-for-rhel-10-x86_64-rpms"
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
# install the PostGIS extension and PostGIS utils
dnf -y install postgis36_18 postgis36_18-utils
Sample Output (click to expand):
[root@lin6 ~]# # verify that the PGDG repositories are available
dnf repolist | grep pgdg
# enable the EPEL repository
subscription-manager repos --enable "codeready-builder-for-rhel-10-x86_64-rpms"
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
# install the PostGIS extension and PostGIS utils
dnf -y install postgis36_18 postgis36_18-utils
pgdg-common                       PostgreSQL common RPMs for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
pgdg14                            PostgreSQL 14 for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
pgdg15                            PostgreSQL 15 for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
pgdg16                            PostgreSQL 16 for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
pgdg17                            PostgreSQL 17 for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
pgdg18                            PostgreSQL 18 for RHEL / Rocky Linux / AlmaLinux 10.2 - x86_64
Repository 'codeready-builder-for-rhel-10-x86_64-rpms' is enabled for this system.
Updating Subscription Management repositories.
Red Hat CodeReady Linux Builder for RHEL 10 x86_64 (RPMs)                                      1.8 MB/s | 1.3 MB     00:00
epel-release-latest-10.noarch.rpm                                                               24 kB/s |  19 kB     00:00
Dependencies resolved.
===============================================================================================================================
 Package                            Arch        Version                   Repository                                      Size
===============================================================================================================================
Installing:
 epel-release                       noarch      10-8.el10_3               @commandline                                    19 k
Installing dependencies:
 selinux-policy-targeted-extra      noarch      42.1.18-4.el10_2.1        codeready-builder-for-rhel-10-x86_64-rpms      777 k
Installing weak dependencies:
 selinux-policy-extra               noarch      42.1.18-4.el10_2.1        codeready-builder-for-rhel-10-x86_64-rpms       43 k

Transaction Summary
===============================================================================================================================
Install  3 Packages

Total size: 838 k
Installed size: 822 k
Downloading Packages:
[SKIPPED] selinux-policy-extra-42.1.18-4.el10_2.1.noarch.rpm: Already downloaded
[SKIPPED] selinux-policy-targeted-extra-42.1.18-4.el10_2.1.noarch.rpm: Already downloaded
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                       1/1
  Running scriptlet: selinux-policy-targeted-extra-42.1.18-4.el10_2.1.noarch                                               1/3
  Installing       : selinux-policy-targeted-extra-42.1.18-4.el10_2.1.noarch                                               1/3
  Installing       : selinux-policy-extra-42.1.18-4.el10_2.1.noarch                                                        2/3
  Installing       : epel-release-10-8.el10_3.noarch                                                                       3/3
  Running scriptlet: epel-release-10-8.el10_3.noarch                                                                       3/3
Many EPEL packages require the CodeReady Builder (CRB) repository.
It is recommended that you run /usr/bin/crb enable to enable the CRB repository.

  Running scriptlet: selinux-policy-targeted-extra-42.1.18-4.el10_2.1.noarch                                               3/3
  Running scriptlet: epel-release-10-8.el10_3.noarch                                                                       3/3
Installed products updated.

Installed:
  epel-release-10-8.el10_3.noarch                                    selinux-policy-extra-42.1.18-4.el10_2.1.noarch
  selinux-policy-targeted-extra-42.1.18-4.el10_2.1.noarch

Complete!
Updating Subscription Management repositories.
Extra Packages for Enterprise Linux 10 - x86_64                                                5.4 MB/s | 6.6 MB     00:01
Last metadata expiration check: 0:00:04 ago on Mon 29 Jul 2026 04:04:19 PM CEST.
Dependencies resolved.
===============================================================================================================================
 Package                            Architecture  Version                       Repository                                Size
===============================================================================================================================
Installing:
 postgis36_18                       x86_64        3.6.3-2PGDG.rhel10.2          pgdg18                                   4.3 M
 postgis36_18-utils                 x86_64        3.6.3-2PGDG.rhel10.2          pgdg18                                    45 k
Installing dependencies:
 SFCGAL-libs                        x86_64        2.2.0-6PGDG.rhel10.2          pgdg-common                              2.9 M
 abseil-cpp                         x86_64        20240722.2-1.el10_2           epel                                     689 k
 armadillo                          x86_64        12.8.1-5.el10_0               epel                                      31 k
 arpack                             x86_64        3.9.1-5.el10_0                epel                                     211 k
 blosc                              x86_64        1.21.6-4.el10_0               epel                                      58 k
 boost-serialization                x86_64        1.83.0-7.el10                 rhel-10-for-x86_64-appstream-rpms        137 k
 cfitsio                            x86_64        4.6.3-1.el10_2                epel                                     624 k
 double-conversion                  x86_64        3.4.0-1.el10_2                epel                                      51 k
 flexiblas                          x86_64        3.4.2-3.el10                  rhel-10-for-x86_64-appstream-rpms         27 k
 flexiblas-netlib                   x86_64        3.4.2-3.el10                  rhel-10-for-x86_64-appstream-rpms        3.2 M
 flexiblas-netlib64                 x86_64        3.4.2-3.el10                  rhel-10-for-x86_64-appstream-rpms        3.1 M
 flexiblas-openblas-openmp          x86_64        3.4.2-3.el10                  rhel-10-for-x86_64-appstream-rpms         19 k
 flexiblas-openblas-openmp64        x86_64        3.4.2-3.el10                  rhel-10-for-x86_64-appstream-rpms         19 k
 freexl                             x86_64        2.0.0-11.el10_0               epel                                      45 k
 gdal312-libs                       x86_64        3.12.4-3PGDG.rhel10.2         pgdg-common                               11 M
 geos314                            x86_64        3.14.1-3PGDG.rhel10.2         pgdg-common                              1.3 M
 gmp-c++                            x86_64        1:6.2.1-12.el10               rhel-10-for-x86_64-appstream-rpms         20 k
 gpsbabel                           x86_64        1.9.0-7.el10_0                epel                                     727 k
 hdf-libs                           x86_64        4.3.0-1.el10_0                epel                                     292 k
 hdf5                               x86_64        1.14.5-1.el10_0               epel                                     2.1 M
 libaec                             x86_64        1.1.3-1.el10_0                epel                                      37 k
 libarrow                           x86_64        17.0.0-9.el10_2               epel                                     5.7 M
 libarrow-doc                       noarch        17.0.0-9.el10_2               epel                                      27 k
 libdeflate                         x86_64        1.25-2.el10_2                 epel                                      66 k
 libgeotiff17                       x86_64        1.7.4-5PGDG.rhel10.2          pgdg-common                              109 k
 libgfortran                        x86_64        14.3.1-4.4.el10               rhel-10-for-x86_64-baseos-rpms           829 k
 libgta                             x86_64        1.2.1-14.el10_0               epel                                      36 k
 libkml                             x86_64        1.3.0-50.el10_0               epel                                     365 k
 liborc2                            x86_64        2.0.7-1.el10_2                epel                                     515 k
 libpq5                             x86_64        18.4-1PGDG.rhel10.2           pgdg-common                              290 k
 libqhull_r                         x86_64        1:8.0.2-2.el10_0              epel                                     204 k
 libquadmath                        x86_64        14.3.1-4.4.el10               rhel-10-for-x86_64-baseos-rpms           217 k
 librttopo                          x86_64        1.1.0-43PGDG.rhel10.2         pgdg-common                              208 k
 libspatialite50                    x86_64        5.1.0-15PGDG.rhel10.2         pgdg-common                              3.1 M
 libzip                             x86_64        1.10.1-5.el10                 rhel-10-for-x86_64-appstream-rpms         70 k
 mariadb-connector-c                x86_64        3.4.4-2.el10_2                rhel-10-for-x86_64-baseos-rpms           217 k
 mariadb-connector-c-config         noarch        3.4.4-2.el10_2                rhel-10-for-x86_64-baseos-rpms            15 k
 minizip-ng-compat                  x86_64        4.0.7-2.el10_0                epel                                      61 k
 netcdf                             x86_64        4.9.2-7.el10_0                epel                                     807 k
 openblas                           x86_64        0.3.29-2.el10                 rhel-10-for-x86_64-appstream-rpms         44 k
 openblas-openmp                    x86_64        0.3.29-2.el10                 rhel-10-for-x86_64-appstream-rpms        5.3 M
 openblas-openmp64                  x86_64        0.3.29-2.el10                 rhel-10-for-x86_64-appstream-rpms        5.2 M
 pcre2-utf16                        x86_64        10.44-1.el10.3                rhel-10-for-x86_64-appstream-rpms        228 k
 perl-DBD-Pg                        x86_64        3.18.0-6.el10                 rhel-10-for-x86_64-appstream-rpms        225 k
 postgresql18-contrib               x86_64        18.4-2PGDG.rhel10.2           pgdg18                                   762 k
 proj98                             x86_64        9.8.1-1PGDG.rhel10.2          pgdg-common                              3.1 M
 protobuf                           x86_64        3.19.6-15.el10_1              rhel-10-for-x86_64-appstream-rpms        1.0 M
 qt5-filesystem                     x86_64        5.15.18-1.el10_2              epel                                     9.8 k
 qt5-qtbase                         x86_64        5.15.18-1.el10_2              epel                                     3.3 M
 qt5-qtbase-common                  noarch        5.15.18-1.el10_2              epel                                      10 k
 re2                                x86_64        2:20251105-1.el10_2           epel                                     221 k
 shapelib                           x86_64        1.6.1-1.el10_0                epel                                      78 k
 unixODBC                           x86_64        2.3.12-6.el10                 rhel-10-for-x86_64-appstream-rpms        500 k
 uriparser                          x86_64        0.9.8-2.el10_1                epel                                      57 k
 utf8proc                           x86_64        2.7.0-9.el10                  rhel-10-for-x86_64-appstream-rpms         83 k
 xerces-c                           x86_64        3.2.5-5.el10_0                epel                                     981 k

Transaction Summary
===============================================================================================================================
Install  58 Packages

Total size: 65 M
Total download size: 807 k
Installed size: 310 M
Downloading Packages:
[SKIPPED] abseil-cpp-20240722.2-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] armadillo-12.8.1-5.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] arpack-3.9.1-5.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] blosc-1.21.6-4.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] cfitsio-4.6.3-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] double-conversion-3.4.0-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] freexl-2.0.0-11.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] gpsbabel-1.9.0-7.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] hdf-libs-4.3.0-1.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] hdf5-1.14.5-1.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] libaec-1.1.3-1.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] libarrow-17.0.0-9.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] libarrow-doc-17.0.0-9.el10_2.noarch.rpm: Already downloaded
[SKIPPED] libdeflate-1.25-2.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] libgta-1.2.1-14.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] libkml-1.3.0-50.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] liborc2-2.0.7-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] libqhull_r-8.0.2-2.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] minizip-ng-compat-4.0.7-2.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] netcdf-4.9.2-7.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] qt5-filesystem-5.15.18-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] qt5-qtbase-5.15.18-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] qt5-qtbase-common-5.15.18-1.el10_2.noarch.rpm: Already downloaded
[SKIPPED] re2-20251105-1.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] shapelib-1.6.1-1.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] uriparser-0.9.8-2.el10_1.x86_64.rpm: Already downloaded
[SKIPPED] xerces-c-3.2.5-5.el10_0.x86_64.rpm: Already downloaded
[SKIPPED] SFCGAL-libs-2.2.0-6PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] gdal312-libs-3.12.4-3PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] geos314-3.14.1-3PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] libgeotiff17-1.7.4-5PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] libpq5-18.4-1PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] librttopo-1.1.0-43PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] libspatialite50-5.1.0-15PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] proj98-9.8.1-1PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] postgis36_18-3.6.3-2PGDG.rhel10.2.x86_64.rpm: Already downloaded
[SKIPPED] libgfortran-14.3.1-4.4.el10.x86_64.rpm: Already downloaded
[SKIPPED] libquadmath-14.3.1-4.4.el10.x86_64.rpm: Already downloaded
[SKIPPED] mariadb-connector-c-3.4.4-2.el10_2.x86_64.rpm: Already downloaded
[SKIPPED] mariadb-connector-c-config-3.4.4-2.el10_2.noarch.rpm: Already downloaded
[SKIPPED] perl-DBD-Pg-3.18.0-6.el10.x86_64.rpm: Already downloaded
[SKIPPED] flexiblas-3.4.2-3.el10.x86_64.rpm: Already downloaded
[SKIPPED] pcre2-utf16-10.44-1.el10.3.x86_64.rpm: Already downloaded
[SKIPPED] utf8proc-2.7.0-9.el10.x86_64.rpm: Already downloaded
[SKIPPED] flexiblas-netlib-3.4.2-3.el10.x86_64.rpm: Already downloaded
[SKIPPED] flexiblas-netlib64-3.4.2-3.el10.x86_64.rpm: Already downloaded
[SKIPPED] flexiblas-openblas-openmp-3.4.2-3.el10.x86_64.rpm: Already downloaded
[SKIPPED] libzip-1.10.1-5.el10.x86_64.rpm: Already downloaded
[SKIPPED] flexiblas-openblas-openmp64-3.4.2-3.el10.x86_64.rpm: Already downloaded
[SKIPPED] unixODBC-2.3.12-6.el10.x86_64.rpm: Already downloaded
[SKIPPED] gmp-c++-6.2.1-12.el10.x86_64.rpm: Already downloaded
[SKIPPED] openblas-0.3.29-2.el10.x86_64.rpm: Already downloaded
[SKIPPED] openblas-openmp-0.3.29-2.el10.x86_64.rpm: Already downloaded
[SKIPPED] openblas-openmp64-0.3.29-2.el10.x86_64.rpm: Already downloaded
[SKIPPED] protobuf-3.19.6-15.el10_1.x86_64.rpm: Already downloaded
[SKIPPED] boost-serialization-1.83.0-7.el10.x86_64.rpm: Already downloaded
(57/58): postgis36_18-utils-3.6.3-2PGDG.rhel10.2.x86_64.rpm                                    408 kB/s |  45 kB     00:00
(58/58): postgresql18-contrib-18.4-2PGDG.rhel10.2.x86_64.rpm                                   3.1 MB/s | 762 kB     00:00
-------------------------------------------------------------------------------------------------------------------------------
Total                                                                                          233 kB/s | 807 kB     00:03
Extra Packages for Enterprise Linux 10 - x86_64                                                1.6 MB/s | 1.6 kB     00:00
Importing GPG key 0xE37ED158:
 Userid     : "Fedora (epel10) <epel@fedoraproject.org>"
 Fingerprint: 7D8D 15CB FC4E 6268 8591 FB26 33D9 8517 E37E D158
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-10
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                       1/1
  Installing       : libgfortran-14.3.1-4.4.el10.x86_64                                                                   1/58
  Installing       : proj98-9.8.1-1PGDG.rhel10.2.x86_64                                                                   2/58
  Running scriptlet: proj98-9.8.1-1PGDG.rhel10.2.x86_64                                                                   2/58
  Installing       : geos314-3.14.1-3PGDG.rhel10.2.x86_64                                                                 3/58
  Running scriptlet: geos314-3.14.1-3PGDG.rhel10.2.x86_64                                                                 3/58
  Installing       : libaec-1.1.3-1.el10_0.x86_64                                                                         4/58
  Installing       : hdf5-1.14.5-1.el10_0.x86_64                                                                          5/58
  Installing       : libpq5-18.4-1PGDG.rhel10.2.x86_64                                                                    6/58
  Running scriptlet: libpq5-18.4-1PGDG.rhel10.2.x86_64                                                                    6/58
  Installing       : hdf-libs-4.3.0-1.el10_0.x86_64                                                                       7/58
  Installing       : libgeotiff17-1.7.4-5PGDG.rhel10.2.x86_64                                                             8/58
  Running scriptlet: libgeotiff17-1.7.4-5PGDG.rhel10.2.x86_64                                                             8/58
  Installing       : openblas-0.3.29-2.el10.x86_64                                                                        9/58
  Installing       : libquadmath-14.3.1-4.4.el10.x86_64                                                                  10/58
  Installing       : xerces-c-3.2.5-5.el10_0.x86_64                                                                      11/58
  Installing       : minizip-ng-compat-4.0.7-2.el10_0.x86_64                                                             12/58
  Installing       : freexl-2.0.0-11.el10_0.x86_64                                                                       13/58
  Installing       : openblas-openmp-0.3.29-2.el10.x86_64                                                                14/58
  Installing       : openblas-openmp64-0.3.29-2.el10.x86_64                                                              15/58
  Installing       : flexiblas-netlib64-3.4.2-3.el10.x86_64                                                              16/58
  Installing       : flexiblas-netlib-3.4.2-3.el10.x86_64                                                                17/58
  Installing       : flexiblas-openblas-openmp-3.4.2-3.el10.x86_64                                                       18/58
  Installing       : flexiblas-3.4.2-3.el10.x86_64                                                                       19/58
  Installing       : flexiblas-openblas-openmp64-3.4.2-3.el10.x86_64                                                     20/58
  Installing       : arpack-3.9.1-5.el10_0.x86_64                                                                        21/58
  Installing       : armadillo-12.8.1-5.el10_0.x86_64                                                                    22/58
  Installing       : postgresql18-contrib-18.4-2PGDG.rhel10.2.x86_64                                                     23/58
  Installing       : perl-DBD-Pg-3.18.0-6.el10.x86_64                                                                    24/58
  Installing       : librttopo-1.1.0-43PGDG.rhel10.2.x86_64                                                              25/58
  Installing       : libspatialite50-5.1.0-15PGDG.rhel10.2.x86_64                                                        26/58
  Running scriptlet: libspatialite50-5.1.0-15PGDG.rhel10.2.x86_64                                                        26/58
  Installing       : boost-serialization-1.83.0-7.el10.x86_64                                                            27/58
  Installing       : protobuf-3.19.6-15.el10_1.x86_64                                                                    28/58
  Installing       : liborc2-2.0.7-1.el10_2.x86_64                                                                       29/58
  Installing       : gmp-c++-1:6.2.1-12.el10.x86_64                                                                      30/58
  Installing       : SFCGAL-libs-2.2.0-6PGDG.rhel10.2.x86_64                                                             31/58
  Running scriptlet: SFCGAL-libs-2.2.0-6PGDG.rhel10.2.x86_64                                                             31/58
  Installing       : unixODBC-2.3.12-6.el10.x86_64                                                                       32/58
  Installing       : libzip-1.10.1-5.el10.x86_64                                                                         33/58
  Installing       : utf8proc-2.7.0-9.el10.x86_64                                                                        34/58
  Installing       : pcre2-utf16-10.44-1.el10.3.x86_64                                                                   35/58
  Installing       : mariadb-connector-c-config-3.4.4-2.el10_2.noarch                                                    36/58
  Installing       : mariadb-connector-c-3.4.4-2.el10_2.x86_64                                                           37/58
  Installing       : uriparser-0.9.8-2.el10_1.x86_64                                                                     38/58
  Installing       : libkml-1.3.0-50.el10_0.x86_64                                                                       39/58
  Installing       : shapelib-1.6.1-1.el10_0.x86_64                                                                      40/58
  Installing       : qt5-filesystem-5.15.18-1.el10_2.x86_64                                                              41/58
  Installing       : libqhull_r-1:8.0.2-2.el10_0.x86_64                                                                  42/58
  Installing       : libgta-1.2.1-14.el10_0.x86_64                                                                       43/58
  Installing       : libdeflate-1.25-2.el10_2.x86_64                                                                     44/58
  Installing       : libarrow-doc-17.0.0-9.el10_2.noarch                                                                 45/58
  Installing       : double-conversion-3.4.0-1.el10_2.x86_64                                                             46/58
  Installing       : qt5-qtbase-common-5.15.18-1.el10_2.noarch                                                           47/58
  Running scriptlet: qt5-qtbase-5.15.18-1.el10_2.x86_64                                                                  48/58
  Installing       : qt5-qtbase-5.15.18-1.el10_2.x86_64                                                                  48/58
  Running scriptlet: qt5-qtbase-5.15.18-1.el10_2.x86_64                                                                  48/58
  Installing       : gpsbabel-1.9.0-7.el10_0.x86_64                                                                      49/58
  Installing       : cfitsio-4.6.3-1.el10_2.x86_64                                                                       50/58
  Installing       : blosc-1.21.6-4.el10_0.x86_64                                                                        51/58
  Installing       : netcdf-4.9.2-7.el10_0.x86_64                                                                        52/58
  Installing       : abseil-cpp-20240722.2-1.el10_2.x86_64                                                               53/58
  Installing       : re2-2:20251105-1.el10_2.x86_64                                                                      54/58
  Installing       : libarrow-17.0.0-9.el10_2.x86_64                                                                     55/58
  Installing       : gdal312-libs-3.12.4-3PGDG.rhel10.2.x86_64                                                           56/58
  Installing       : postgis36_18-3.6.3-2PGDG.rhel10.2.x86_64                                                            57/58
  Installing       : postgis36_18-utils-3.6.3-2PGDG.rhel10.2.x86_64                                                      58/58
  Running scriptlet: postgis36_18-utils-3.6.3-2PGDG.rhel10.2.x86_64                                                      58/58
Installed products updated.

Installed:
  SFCGAL-libs-2.2.0-6PGDG.rhel10.2.x86_64                         abseil-cpp-20240722.2-1.el10_2.x86_64
  armadillo-12.8.1-5.el10_0.x86_64                                arpack-3.9.1-5.el10_0.x86_64
  blosc-1.21.6-4.el10_0.x86_64                                    boost-serialization-1.83.0-7.el10.x86_64
  cfitsio-4.6.3-1.el10_2.x86_64                                   double-conversion-3.4.0-1.el10_2.x86_64
  flexiblas-3.4.2-3.el10.x86_64                                   flexiblas-netlib-3.4.2-3.el10.x86_64
  flexiblas-netlib64-3.4.2-3.el10.x86_64                          flexiblas-openblas-openmp-3.4.2-3.el10.x86_64
  flexiblas-openblas-openmp64-3.4.2-3.el10.x86_64                 freexl-2.0.0-11.el10_0.x86_64
  gdal312-libs-3.12.4-3PGDG.rhel10.2.x86_64                       geos314-3.14.1-3PGDG.rhel10.2.x86_64
  gmp-c++-1:6.2.1-12.el10.x86_64                                  gpsbabel-1.9.0-7.el10_0.x86_64
  hdf-libs-4.3.0-1.el10_0.x86_64                                  hdf5-1.14.5-1.el10_0.x86_64
  libaec-1.1.3-1.el10_0.x86_64                                    libarrow-17.0.0-9.el10_2.x86_64
  libarrow-doc-17.0.0-9.el10_2.noarch                             libdeflate-1.25-2.el10_2.x86_64
  libgeotiff17-1.7.4-5PGDG.rhel10.2.x86_64                        libgfortran-14.3.1-4.4.el10.x86_64
  libgta-1.2.1-14.el10_0.x86_64                                   libkml-1.3.0-50.el10_0.x86_64
  liborc2-2.0.7-1.el10_2.x86_64                                   libpq5-18.4-1PGDG.rhel10.2.x86_64
  libqhull_r-1:8.0.2-2.el10_0.x86_64                              libquadmath-14.3.1-4.4.el10.x86_64
  librttopo-1.1.0-43PGDG.rhel10.2.x86_64                          libspatialite50-5.1.0-15PGDG.rhel10.2.x86_64
  libzip-1.10.1-5.el10.x86_64                                     mariadb-connector-c-3.4.4-2.el10_2.x86_64
  mariadb-connector-c-config-3.4.4-2.el10_2.noarch                minizip-ng-compat-4.0.7-2.el10_0.x86_64
  netcdf-4.9.2-7.el10_0.x86_64                                    openblas-0.3.29-2.el10.x86_64
  openblas-openmp-0.3.29-2.el10.x86_64                            openblas-openmp64-0.3.29-2.el10.x86_64
  pcre2-utf16-10.44-1.el10.3.x86_64                               perl-DBD-Pg-3.18.0-6.el10.x86_64
  postgis36_18-3.6.3-2PGDG.rhel10.2.x86_64                        postgis36_18-utils-3.6.3-2PGDG.rhel10.2.x86_64
  postgresql18-contrib-18.4-2PGDG.rhel10.2.x86_64                 proj98-9.8.1-1PGDG.rhel10.2.x86_64
  protobuf-3.19.6-15.el10_1.x86_64                                qt5-filesystem-5.15.18-1.el10_2.x86_64
  qt5-qtbase-5.15.18-1.el10_2.x86_64                              qt5-qtbase-common-5.15.18-1.el10_2.noarch
  re2-2:20251105-1.el10_2.x86_64                                  shapelib-1.6.1-1.el10_0.x86_64
  unixODBC-2.3.12-6.el10.x86_64                                   uriparser-0.9.8-2.el10_1.x86_64
  utf8proc-2.7.0-9.el10.x86_64                                    xerces-c-3.2.5-5.el10_0.x86_64

Complete!
[root@lin6 ~]#

Creating a Spatial Database

We will now create a new (standard) PostgreSQL database and enable the PostGIS extension for this database:

# run as the postgres user
# create the database
createdb gisdemo
psql gisdemo <<EOF
-- enable the PostGIS extension
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;
-- verify the installation:
SELECT PostGIS_Full_Version();
\q
EOF

Sample Output (click to expand):
[postgres@lin6 ~]$ # run as the postgres user
# create the database
createdb gisdemo
psql gisdemo <<EOF
-- enable the PostGIS extension
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;
-- verify the installation:
SELECT PostGIS_Full_Version();
\q
EOF

CREATE EXTENSION
CREATE EXTENSION
                                                                                                                                                                         postgis_full_version                                                                 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 POSTGIS="3.6.3 3d12666" [EXTENSION] PGSQL="180" GEOS="3.14.1-CAPI-1.20.5" PROJ="9.8.1 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org USER_WRITABLE_DIRECTORY=/var/lib/pgsql/.local/share/proj DATABASE_PATH=/usr/proj98/share/proj/proj.db" (compiled against PROJ 9.8.1) LIBXML="2.12.5" LIBJSON="0.18" LIBPROTOBUF="1.5.0" WAGYU="0.5.0 (Internal)" TOPOLOGY
(1 row)

[postgres@lin6 ~]$

The PostgreSQL database is now capable of storing and processing spatial data.

Understanding Geometry

Unlike traditional databases, PostGIS introduces geometry data types.

Create a simple table:

psql gisdemo <<EOF
CREATE TABLE cities (
    id serial PRIMARY KEY,
    name text,
    population integer,
    location geometry(Point,4326)
);
EOF

The important part is:

geometry(Point,4326)

This means:

  • Point geometry
  • Coordinate reference system EPSG:4326 (WGS84)

This is the coordinate system used by GPS and OpenStreetMap.

Inserting Data

Let’s insert a few German cities.

psql gisdemo <<EOF
INSERT INTO cities (name,population,location)
VALUES ('Munich',1590000, ST_SetSRID(ST_Point(11.5820,48.1351),4326));
INSERT INTO cities (name,population,location)
VALUES ('Berlin',3890000, ST_SetSRID(ST_Point(13.4050,52.5200),4326));
INSERT INTO cities (name,population,location)
VALUES ('Leipzig',620000, ST_SetSRID(ST_Point(12.3731,51.3397),4326));
EOF

Verify the inserted data:

psql gisdemo <<EOF
SELECT name, ST_AsText(location) FROM cities;
EOF
Output (click to expand):
[postgres@lin6 ~]$ psql gisdemo <<EOF
SELECT name, ST_AsText(location) FROM cities;
EOF
  name   |       st_astext
---------+------------------------
 Munich  | POINT(11.582 48.1351)
 Berlin  | POINT(13.405 52.52)
 Leipzig | POINT(12.3731 51.3397)
(3 rows)

[postgres@lin6 ~]$

Your First Spatial Query

Calculate the distance between Munich and Berlin.

psql gisdemo <<EOF
SELECT
ST_Distance(
  (SELECT location FROM cities WHERE name='Munich')::geography,
  (SELECT location FROM cities WHERE name='Berlin')::geography
)/1000 AS distance_km;
EOF
Output (click to expand):
[postgres@lin6 ~]$ psql gisdemo <<EOF
SELECT
ST_Distance(
  (SELECT location FROM cities WHERE name='Munich')::geography,
  (SELECT location FROM cities WHERE name='Berlin')::geography
)/1000 AS distance_km;
EOF
    distance_km
--------------------
 504.68941124585996
(1 row)

[postgres@lin6 ~]$

Unlike ordinary SQL databases, PostGIS understands the Earth’s curvature and returns accurate geographic distances.

Importing Real-World Data

While the sample data is useful for learning SQL syntax, it is too small to demonstrate indexing, query optimization, or database maintenance.

For the remainder of this series, we’ll use OpenStreetMap (OSM) data imported into PostgreSQL with osm2pgsql. This provides a realistic workload containing roads, buildings, waterways, parks, railways, and other spatial objects.

Download a regional extract from Geofabrik and import it. For example, to work with Bavaria:

# run as root
# install osm2pgsql
dnf -y install osm2pgsql
# download the dataset
su - postgres -c 'wget https://download.geofabrik.de/europe/germany/bayern-latest.osm.pbf'
# load the data into the gisdemo database
su - postgres -c 'osm2pgsql --database gisdemo --create --slim bayern-latest.osm.pbf'
Output (click to expand):
[root@lin6 ~]# # run as root
# install osm2pgsql
dnf -y install osm2pgsql
# download the dataset
su - postgres -c 'wget https://download.geofabrik.de/europe/germany/bayern-latest.osm.pbf'
# load the data into the gisdemo database
su - postgres -c 'osm2pgsql --database gisdemo --create --slim bayern-latest.osm.pbf'
Updating Subscription Management repositories.
Last metadata expiration check: 0:26:35 ago on Mon 29 Jul 2026 04:04:19 PM CEST.
Dependencies resolved.
===============================================================================================================================
 Package                    Architecture            Version                                 Repository                    Size
===============================================================================================================================
Installing:
 osm2pgsql                  x86_64                  2.3.1-1PGDG.rhel10.2                    pgdg-common                  1.3 M

Transaction Summary
===============================================================================================================================
Install  1 Package

Total download size: 1.3 M
Installed size: 4.9 M
Downloading Packages:
osm2pgsql-2.3.1-1PGDG.rhel10.2.x86_64.rpm                                                      3.7 MB/s | 1.3 MB     00:00
-------------------------------------------------------------------------------------------------------------------------------
Total                                                                                          3.7 MB/s | 1.3 MB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                       1/1
  Installing       : osm2pgsql-2.3.1-1PGDG.rhel10.2.x86_64                                                                 1/1
  Running scriptlet: osm2pgsql-2.3.1-1PGDG.rhel10.2.x86_64                                                                 1/1
Installed products updated.

Installed:
  osm2pgsql-2.3.1-1PGDG.rhel10.2.x86_64

Complete!
--2026-07-29 16:30:59--  https://download.geofabrik.de/europe/germany/bayern-latest.osm.pbf
Resolving download.geofabrik.de (download.geofabrik.de)... 95.217.63.98, 95.216.245.185, 95.217.45.61, ...
Connecting to download.geofabrik.de (download.geofabrik.de)|95.217.63.98|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://download.geofabrik.de/europe/germany/bayern-260726.osm.pbf [following]
--2026-07-29 16:30:59--  https://download.geofabrik.de/europe/germany/bayern-260726.osm.pbf
Reusing existing connection to download.geofabrik.de:443.
HTTP request sent, awaiting response... 200 OK
Length: 847075950 (808M) [application/octet-stream]
Saving to: ‘bayern-latest.osm.pbf’

bayern-latest.osm.pbf           100%[======================================================>] 807.83M  12.1MB/s    in 83s

2026-07-29 16:32:23 (9.68 MB/s) - ‘bayern-latest.osm.pbf’ saved [847075950/847075950]

2026-07-29 16:32:23  osm2pgsql version 2.3.1
2026-07-29 16:32:23  Database version: 18.4
2026-07-29 16:32:23  PostGIS version: 3.6
2026-07-29 16:32:23  WARNING: The pgsql (default) output is deprecated. For details see https://osm2pgsql.org/doc/faq.html#the-pgsql-output-is-deprecated-what-does-that-mean
2026-07-29 16:32:23  Initializing properties table '"public"."osm2pgsql_properties"'.
2026-07-29 16:32:23  Storing properties to table '"public"."osm2pgsql_properties"'.
2026-07-29 16:32:23  Setting up table 'planet_osm_point'
2026-07-29 16:32:23  Setting up table 'planet_osm_line'
2026-07-29 16:32:23  Setting up table 'planet_osm_polygon'
2026-07-29 16:32:23  Setting up table 'planet_osm_roads'
2026-07-29 16:44:34  Reading input files done in 731s (12m 11s).
2026-07-29 16:44:34    Processed 80056630 nodes in 260s (4m 20s) - 308k/s
2026-07-29 16:44:34    Processed 11836998 ways in 243s (4m 3s) - 49k/s
2026-07-29 16:44:34    Processed 142696 relations in 228s (3m 48s) - 626/s
2026-07-29 16:44:34  Clustering table 'planet_osm_line' by geometry...
2026-07-29 16:44:34  Clustering table 'planet_osm_polygon' by geometry...
2026-07-29 16:44:34  Clustering table 'planet_osm_roads' by geometry...
2026-07-29 16:44:34  Clustering table 'planet_osm_point' by geometry...
2026-07-29 16:44:34  Building index on middle ways table
2026-07-29 16:44:34  Building indexes on middle rels table
2026-07-29 16:44:34  Done postprocessing on table 'planet_osm_nodes' in 0s
2026-07-29 16:44:41  Creating geometry index on table 'planet_osm_roads'...
2026-07-29 16:44:47  Creating osm_id index on table 'planet_osm_roads'...
2026-07-29 16:44:49  Analyzing table 'planet_osm_roads'...
2026-07-29 16:45:01  Creating geometry index on table 'planet_osm_point'...
2026-07-29 16:45:23  Creating osm_id index on table 'planet_osm_point'...
2026-07-29 16:45:28  Analyzing table 'planet_osm_point'...
2026-07-29 16:46:39  Creating geometry index on table 'planet_osm_line'...
2026-07-29 16:47:11  Creating osm_id index on table 'planet_osm_line'...
2026-07-29 16:47:18  Analyzing table 'planet_osm_line'...
2026-07-29 16:47:19  Creating geometry index on table 'planet_osm_polygon'...
2026-07-29 16:48:14  Creating osm_id index on table 'planet_osm_polygon'...
2026-07-29 16:48:24  Analyzing table 'planet_osm_polygon'...
2026-07-29 16:51:02  Done postprocessing on table 'planet_osm_ways' in 368s (6m 8s)
2026-07-29 16:51:02  Done postprocessing on table 'planet_osm_rels' in 42s
2026-07-29 16:51:02  All postprocessing on table 'planet_osm_point' done in 54s.
2026-07-29 16:51:02  All postprocessing on table 'planet_osm_line' done in 165s (2m 45s).
2026-07-29 16:51:02  All postprocessing on table 'planet_osm_polygon' done in 232s (3m 52s).
2026-07-29 16:51:02  All postprocessing on table 'planet_osm_roads' done in 18s.
2026-07-29 16:51:02  Storing properties to table '"public"."osm2pgsql_properties"'.
2026-07-29 16:51:02  osm2pgsql took 1118s (18m 38s) overall.
[root@lin6 ~]#

The import takes around 20 minutes and creates millions of rows.

Visualizing the Data

Data becomes much easier to understand when you can see it on a map.

In the next article, we’ll build a lightweight web application using Leaflet that displays our PostgreSQL/PostGIS data directly in a browser. This application will become our test platform for exploring query optimization, spatial indexes, execution plans, and database tuning.

What’s Next?

This article establishes the foundation for the rest of the series. In upcoming posts we’ll cover topics such as:

By working with a realistic dataset instead of isolated examples, every optimization and maintenance task can be demonstrated using practical scenarios similar to those found in production environments.

Conclusion

Installing PostGIS is only the first step. The real value comes from working with real-world spatial data and understanding how PostgreSQL processes geographic information. Throughout this series we’ll evolve this simple installation into a production-style GIS platform, providing practical examples of administration, performance tuning, and operational best practices for PostgreSQL and PostGIS.

0