Skip Navigation

Geoformatting API Service

ESRGC · February 2024 - February 2025

Microservice for converting multiple GIS data file formats into a common GeoJSON format for use in different web mapping libraries.

Tech Used
PythonFastAPIGeoPandasDockerDigitalOcean

Background

The Geoformatting Service began with a practical problem in MART. Users can map their agricultural fields in the application, and some already have those boundaries stored in GIS files. MART needed to accept several file formats and display their geometries as polygons without adding a separate storage and parsing workflow for every type of source data.

GeoJSON was a natural common format for the web map, but the JavaScript conversion options I evaluated introduced more complexity than the feature justified. Python's GeoPandas library already handled the required geospatial formats and transformations cleanly. I used it to build a focused conversion service that now supports both MART and the Maryland Coastal Flood Explorer.

How it evolved

The first version converted Shapefiles and KML files into GeoJSON. Because it existed only to serve MART, its API and implementation were initially coupled to that application's workflow. I later added support for converting ArcGIS Sketch data, but it remained an internal component of the MART codebase.

During development of the Maryland Coastal Flood Explorer, project partners requested a similar feature: users needed to add their own GIS files to the web map and view them alongside the application's existing flood and reference layers. Rather than duplicate the conversion logic, I separated the service from MART, moved it into its own repository, and generalized the API for use by multiple applications. I also added KMZ conversion to support MCFE's requirements.

The result is a small shared service with a deliberately narrow responsibility. New applications can rely on one conversion workflow, and support for additional formats can be added without embedding format-specific parsing code throughout each front end.

Technical approach

At its core, the service is a lightweight REST API built with FastAPI. Its endpoints wrap a small set of GeoPandas operations along with the arcgis2geojson Python package, converting supported inputs into GeoJSON that browser-based mapping libraries can consume directly. This keeps the web applications focused on validation, interaction, and visualization while the geospatial processing remains in the ecosystem best suited to it.

MART was hosted on Vercel when I developed the first version, so I initially tested whether the conversion logic could run there as a serverless function. The geospatial dependencies and processing requirements exceeded the platform's practical size and memory constraints. After confirming that limitation, I kept the service boundary but changed the deployment model rather than forcing the workload into an unsuitable environment.

I rebuilt the API with FastAPI, packaged it with Docker, and deployed it to a DigitalOcean Droplet. That approach provides the runtime and native geospatial dependencies the service needs while keeping deployment repeatable. Separating it from MART also turned an application-specific helper into reusable infrastructure without expanding it into a larger platform than the problem required.

Challenges and lessons

The most important decision was not a complicated algorithm; it was choosing the right boundary and language for a small piece of the system. I could have continued assembling JavaScript libraries for each input type, but that would have increased application complexity to avoid operating a modest Python service. GeoPandas provided the required GIS capabilities directly, making Python the more maintainable choice even though most of my ESRGC application work uses TypeScript.

The failed serverless deployment was also a useful reminder that a sound software abstraction does not guarantee a suitable hosting model. By preserving the conversion service while changing how it was deployed, I kept the architecture simple and matched the infrastructure to the workload.

This project demonstrates the value of extracting shared functionality at the right time. The first tightly coupled implementation was appropriate when MART was the only consumer. Once MCFE presented the same need, I generalized the API and deployment so both applications could benefit without duplicating code. The service remains intentionally small, but it has become a flexible piece of geospatial infrastructure that can support additional formats and projects with minimal disruption.