GeoJSON Best Practices for Developers
Best practices for working with GeoJSON data in web mapping and GIS applications.
Keep File Sizes Small
GeoJSON is verbose by nature. Large files slow down APIs, browsers, and map rendering. Practical strategies to reduce size:
- Reduce coordinate precision — 6 decimal places gives ~0.1 meter accuracy, which is more than enough for most web maps. Use our Coordinate Precision Tool to trim excess decimals.
- Simplify geometries — Remove unnecessary vertices from complex polygons and lines. Our GeoJSON Simplifier uses the Douglas-Peucker algorithm to reduce complexity while preserving shape.
- Minify the JSON — Strip whitespace and formatting for production use with our GeoJSON Minifier.
- Consider alternatives for large datasets — For files over 10–20 MB, look into vector tiles, FlatGeobuf, or GeoParquet instead.
Always Use [Longitude, Latitude] Order
The single most common GeoJSON bug is swapping latitude and longitude. GeoJSON coordinates are [longitude, latitude] — not the [lat, lng] order used by Google Maps, Leaflet's L.latLng(), and most geocoding APIs.
A point in New York City:
GeoJSON// Correct
"coordinates": [-74.006, 40.7128]
// Wrong — this puts you in China
"coordinates": [40.7128, -74.006]If your points are appearing in the wrong place, coordinate order is almost always the reason. Use our Coordinate Flip Tool to fix swapped coordinates.
Validate Early and Often
Don't wait until something breaks in production. Validate your GeoJSON during development:
- Check against RFC 7946 with our GeoJSON Validator
- Verify polygon rings are closed (first and last coordinate must match)
- Confirm winding order is correct (exterior CCW, holes CW) — use our Rewind Tool
- Ensure all Features have a
"type": "Feature"member
Use FeatureCollection as Your Top-Level Object
Even if you only have one feature, wrap it in a FeatureCollection:
GeoJSON{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-73.9857, 40.7484] },
"properties": { "name": "Empire State Building" }
}
]
}This makes your data consistent and forward-compatible — adding more features later doesn't require changing the structure. Most tools and libraries expect FeatureCollections.
Put Metadata in properties, Not Custom Top-Level Fields
The properties object is where all non-spatial attributes belong:
GeoJSON// Good
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-0.1276, 51.5074] },
"properties": {
"name": "London",
"population": 8982000,
"country": "United Kingdom"
}
}
// Avoid — "name" as a foreign member
{
"type": "Feature",
"name": "London",
"geometry": { "type": "Point", "coordinates": [-0.1276, 51.5074] },
"properties": {}
}The exception is id — RFC 7946 explicitly allows an id member on Feature objects.
Include a bbox for Large Datasets
Adding a bounding box helps mapping libraries quickly determine if the data is relevant to the current viewport without scanning every coordinate:
GeoJSON{
"type": "FeatureCollection",
"bbox": [-10.5, 49.5, 2.0, 59.0],
"features": [ ... ]
}Use our Bounding Box Calculator to compute it.
Use Meaningful Property Names
Choose clear, consistent property keys. Consider conventions used by OpenStreetMap, GeoNames, or your domain:
GeoJSON// Clear and consistent
"properties": {
"name": "Hyde Park",
"area_km2": 1.42,
"type": "park",
"accessible": true
}
// Unclear
"properties": {
"n": "Hyde Park",
"a": 1.42,
"t": "p",
"acc": true
}Abbreviated keys save bytes but cost readability. If file size is a concern, minify the JSON instead of shortening property names.
Handle Null Geometries Gracefully
A Feature with a null geometry is valid GeoJSON. This represents a feature with properties but no location — for example, a record where the coordinates are unknown:
GeoJSON{
"type": "Feature",
"geometry": null,
"properties": {
"name": "Unknown Location Site",
"status": "pending_survey"
}
}Make sure your code handles null geometries without crashing.
Close Your Polygon Rings
Every polygon ring must end with the same coordinate it started with. This is a common source of validation errors:
GeoJSON// Correct — ring is closed
"coordinates": [
[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]
]
// Invalid — ring is not closed
"coordinates": [
[0, 0], [10, 0], [10, 10], [0, 10]
]Follow the Right-Hand Rule for Polygons
Per RFC 7946, exterior polygon rings should be wound counterclockwise (CCW) and holes should be wound clockwise (CW). While many parsers accept either order, following the spec avoids subtle rendering bugs — especially with fill rules.
Use our Rewind Tool to fix winding order automatically.
Use id for Feature Identity
When features need stable identifiers (for styling, filtering, or updates), use the id member rather than burying it in properties:
GeoJSON{
"type": "Feature",
"id": "building-42",
"geometry": { "type": "Point", "coordinates": [-0.1276, 51.5074] },
"properties": { "name": "Main Office" }
}Mapbox GL JS and other libraries use this id for feature state management and efficient updates.
Test with Real Mapping Libraries
GeoJSON that parses correctly as JSON may still render incorrectly on a map. Test your data with the actual libraries you're targeting:
- Leaflet —
L.geoJSON(data).addTo(map) - Mapbox GL JS —
map.addSource('data', { type: 'geojson', data }) - Google Maps —
map.data.addGeoJson(data) - ArcGIS JavaScript API —
GeoJSONLayer({ url }) - D3.js —
d3.geoPath()(feature)
Or simply paste your GeoJSON into our GeoJSON Viewer for a quick visual check.