Migrate a geodatabase to GeoPackage and PostGIS without losing data meaning
Inventory domains, relationships, attachments and identifiers before converting a geodatabase.
Editorial review: 2026-09-23
Geometry conversion is not equivalent to migrating a geodatabase. Tables may open successfully while editing rules, relationships or attachment lookup behavior disappear. Work from an authorized copy, retain a read-only original and define which consumers must continue working.
Inventory before conversion
With a GDAL build containing OpenFileGDB, inspect layers, fields, CRS, identifiers and counts. Support depends on the version and the features used in the file. Pay particular attention to 64-bit identifier restrictions; do not assume every format preserves OBJECTID values.
ogrinfo -ro -so -al source.gdb
ogr2ogr -f GPKG pilot.gpkg source.gdb parcels -nln parcels
ogrinfo -ro -so pilot.gpkg parcels
Run the conversion in a fresh directory where pilot.gpkg does not exist. The command exports the inventoried parcels layer; replace that layer name rather than using a production destination. The expected result is a readable layer with the same eligible feature count. This does not yet prove preservation of business rules.
Validate more than row counts
Compare types, numeric precision, text lengths, nulls, dates, multipart geometries and coded values. A displayed category name may come from a domain interpreted automatically by the old application. Decide whether to preserve the code and rebuild its lookup table or materialize an additional label; retain a stable business key either way.
Test a parent-child relationship with known records, a sample attachment and an empty geometry. Relationship support in a driver does not guarantee that a destination format or client consumes it identically. Attribute rules, topologies, networks and versioning need explicit design rather than an assumption of equivalence between file extensions.
Move to PostGIS for concurrency
Configure a local gis_lab connection in the PostgreSQL service file and manage authentication outside the command. Import into a previously created, empty test schema:
ogr2ogr -f PostgreSQL 'PG:service=gis_lab' pilot.gpkg parcels -nln staging.parcels
Do not use -overwrite against an operational table. Recheck counts, keys and CRS, create indexes according to real queries and grant minimal permissions. If external systems depend on existing identifiers, prepare a mapping between the original business key and the new technical key.
Acceptance criteria
Open the copy in QGIS and every retained client. Retrieve a feature by its key, edit a permitted attribute, reject an out-of-domain value and retrieve an attachment. Document which rules now live in the database, which live in forms and which require development. Keep the original available until those tests pass and a rollback path exists. A conversion completing without errors is insufficient evidence for cutover.
Build a preservation matrix before the first export
Create a small migration inventory with one row per object type. A department may have ten feature classes but only two business relationships that make the system operational. Those relationships deserve explicit tests.
| Source element | Proposed destination | Evidence required |
|---|---|---|
| Business identifier | Unique text or UUID column | Exact match including leading zeros |
| OBJECTID | Destination technical key plus mapping if required | Links and external consumers still resolve |
| Coded domain | Reference table or constraint; QGIS value relation | Invalid code rejected by the write path |
| Parent-child relationship | Foreign key and configured client relation | Known parent retrieves the expected children |
| Attachment | File or object storage plus attachment metadata | Correct owner, content type and retrievable bytes |
| Editor tracking | Agreed audit fields or controlled audit process | Who changed what and when remains attributable |
| Topology/network rule | Separate validation or retained component | Deliberate violation detected in the pilot |
Do not rename identifiers, translate codes and reproject geometry in the same first export. Separate these transformations so a discrepancy has an identifiable cause. Preserve text identifiers such as 00042; converting them to integers changes their meaning even when counts match.
A three-pass validation procedure
- Structural pass. Compare table names, fields, types, field widths, precision, nullability, geometry type, Z/M dimensions and CRS. Capture the installed GDAL version with
ogrinfo --version. Read the OpenFileGDB driver documentation for that version rather than assuming that every workstation has the same capabilities. - Relationship pass. Select a parent with zero children, one with one child and one with several children. Include an attachment with an accented filename and an empty optional field. Verify identifiers before comparing display labels. Check for orphan records using the target relationship key.
- Behavior pass. Open the target through each retained client. Attempt a valid insert, an invalid domain value, an invalid relationship and an edit followed by rollback. A read-only map test does not validate these operations.
For a target model with assets(asset_id) and inspections(asset_id), an orphan check is:
SELECT i.asset_id, count(*)
FROM staging.inspections AS i
LEFT JOIN staging.assets AS a ON a.asset_id = i.asset_id
WHERE a.asset_id IS NULL
GROUP BY i.asset_id;
Zero rows is the expected result only when every inspection must reference an asset. A legitimate historical orphan requires an explicit migration rule; silently deleting it makes the count look cleaner while losing evidence.
Decide between GeoPackage and PostGIS
Choose GeoPackage for a portable pilot, an exchange deliverable or a bounded offline package. Choose a managed PostGIS workflow when shared editing, service access, centrally enforced constraints and recoverable server operations are requirements. It is also reasonable to use both: PostGIS as the central store and GeoPackage as a controlled exchange format.
Exporting to GeoPackage does not automatically preserve every geodatabase behavior. GDAL's ability to expose domains or relationships is separate from whether a conversion command copies them and whether a client interprets them. Inspect the result, especially when different GDAL versions are bundled with QGIS and the command line.
Freeze, reconcile and reverse the cutover
Agree which system is writable during the final migration window. If both remain writable, define how changes are identified and reconciled; timestamps alone can miss deletes or clock differences. Keep an immutable authorized source snapshot and a record of the converted version. Reconcile the final batch, then switch a bounded group of users and monitor rejected edits and unresolved links.
Rollback should say which system becomes authoritative, how edits created after cutover are preserved, and who resolves divergence. “Restore yesterday's backup” can lose today's work. Use the synthetic laboratory to rehearse the procedure before adding private attachments or production connections.
Sources and documentation
Next step
Continue in the Open GIS collection. For a specific project, use the total-cost calculator and request an assessment.