Custom Polygons vs. Uber's H3: Building a High-Performance Geofencing Backend in Go
<p>When building logistics and telemetry platforms, processing thousands of GPS pings per second is just a regular Tuesday. The core challenge isn't just receiving the data; it's figuring out <em>exactly</em> where that data is in relation to your business logic. Is the truck inside the warehouse? Did it cross a restricted zone?<br> <br></p> <p>If you are building a geofencing architecture, you will inevitably face the dilemma: <strong>Should you use exact Custom Polygons (PostGIS) or spatial indexing grids like Uber's H3?</strong></p> <p>Spoiler alert: For a truly scalable and user-friendly system, you need both. Here is how we handle this hybrid architecture using Go and PostGIS.<br> <br></p> <h2> The Reality: Users Don't Think in Hexagons </h2> <p>From a purely mathematical standpoint,
When building logistics and telemetry platforms, processing thousands of GPS pings per second is just a regular Tuesday. The core challenge isn't just receiving the data; it's figuring out exactly where that data is in relation to your business logic. Is the truck inside the warehouse? Did it cross a restricted zone?
If you are building a geofencing architecture, you will inevitably face the dilemma: Should you use exact Custom Polygons (PostGIS) or spatial indexing grids like Uber's H3?
Spoiler alert: For a truly scalable and user-friendly system, you need both. Here is how we handle this hybrid architecture using Go and PostGIS.
The Reality: Users Don't Think in Hexagons
From a purely mathematical standpoint, Uber’s H3 is a masterpiece. But from a UX perspective, telling a warehouse manager to draw their loading dock using only rigid hexagons is a terrible idea. Real-world facilities (like a CEDIS or a distribution center) are irregular.
Users need to draw custom polygons on a map. In our Go backend, we typically store these directly in PostgreSQL using PostGIS.
The Standard Approach: PostGIS ST_Contains
When a GPS ping hits our Go server, the most straightforward approach is to ask PostGIS if the point is inside any stored polygon.
// A simplified example of checking a GPS ping against PostGIS polygons package main// A simplified example of checking a GPS ping against PostGIS polygons package mainimport ( "database/sql" "fmt" "log"
_ "github.com/lib/pq" )_
func checkGeofence(db sql.DB, lat, lng float64) (string, error) {
query := SELECT fence_id, name FROM geofences WHERE ST_Contains(geom, ST_SetSRID(ST_MakePoint($1, $2), 4326)); SELECT fence_id, name FROM geofences WHERE ST_Contains(geom, ST_SetSRID(ST_MakePoint($1, $2), 4326));
var fenceID, name string err := db.QueryRow(query, lng, lat).Scan(&fenceID, &name) if err != nil { if err == sql.ErrNoRows { return "", nil // Not in any geofence } return "", err }
return name, nil }`
Enter fullscreen mode
Exit fullscreen mode
The Catch: ST_Contains uses spatial math (like ray casting) to determine if a point is inside a polygon. Even with GiST indexes, running complex spatial intersections for 10,000 pings per second will melt your database CPU and spike your cloud bill.
The Scaling Secret: Enter Uber's H3
When we need to eliminate database latency and scale massively, we bring H3 into the backend.
H3 divides the world into a grid of hexagons. Instead of doing complex math, H3 converts a (latitude, longitude) pair into a simple string or integer (e.g., 8928308280fffff).
Why is this a game-changer? Because checking if a truck is in a zone goes from an expensive spatial calculation to an $O(1)$ Hash Map lookup.
The Hybrid Architecture: "Polyfill"
We don't force users to draw hexagons. We let them draw their precise custom polygons. Then, in the Go backend, we run an asynchronous worker that takes that polygon and "fills" it with H3 hexagons (a process called Polyfill).
We store these hexagon IDs in a fast key-value store (like Redis) or a simple indexed database table.
package main
import ( "fmt" "github.com/uber/h3-go/v4" )
func indexGeofenceWithH3(polygon []h3.LatLng, resolution int) []h3.Cell { // Create a GeoLoop from the user's custom polygon geoLoop := h3.NewGeoLoop(polygon) geoPolygon := h3.NewGeoPolygon(geoLoop, nil)
// Fill the polygon with H3 hexagons at the desired resolution hexagons := h3.PolygonToCells(geoPolygon, resolution)
return hexagons }
func handleIncomingPing(lat, lng float64) { // 1. Convert incoming ping to H3 index instantly latLng := h3.NewLatLng(lat, lng) resolution := 9 // Roughly city-block size cell := h3.LatLngToCell(latLng, resolution)
// 2. O(1) Lookup: Check if this cell ID exists in our Redis cache // cache.Exists(cell.String()) fmt.Printf("Ping mapped to Hexagon: %s\n", cell.String()) }`
Enter fullscreen mode
Exit fullscreen mode
The Best of Both Worlds
By using Go, PostGIS, and H3 together, you build a logistics engine that is both precise and brutally fast:
-
UX / Precision: Users draw exact custom polygons.
-
Storage: PostGIS acts as the source of truth for the exact geometries.
-
Real-Time Processing: Go converts incoming pings to H3 indexes and checks them against a cached set of Polyfilled hexagons in microseconds.
There is no silver bullet in software engineering, but for real-time logistics telemetry, combining PostGIS precision with H3 speed is as close as it gets.
Sign in to highlight and annotate this article

Conversation starters
Daily AI Digest
Get the top 5 AI stories delivered to your inbox every morning.
More about
platformperspectiverestrict
QUANTUM HORIZONS Your Passwords Have an Expiry Date. Nobody Told You.
By The Architect NEO | April 2026 You know that friend? The one at every barbecue who, somewhere between the third burger and the dying embers, starts talking about encryption? The one who makes you check if your webcam has tape over it? The one who said "don't use that free Wi-Fi" at the airport in 2019 and you thought they were being dramatic? That friend was right about everything. And they're about to be right again — about something much, much bigger. THE QUIET HEIST NOBODY'S REPORTING Right now, while you're reading this on a Tuesday lunchbreak or doomscrolling at 11pm, encrypted data is being stolen. Not decrypted. Not read. Not yet. Stored. Intelligence agencies across the globe have a name for it: "Harvest Now, Decrypt Later." The idea is brutally simple. Steal encrypted data toda

Cloud Observability vs Monitoring: What's the Difference and Why It Matters
Cloud Observability vs Monitoring: What's the Difference and Why It Matters Your alerting fires at 2 AM. CPU is at 94%, error rate is at 6.2%, and latency is climbing. You page the on-call engineer. They open the dashboard. They see the numbers going up. What they cannot see is why — because the service throwing errors depends on three upstream services, one of which depends on a database that is waiting on a connection pool that was quietly exhausted by a batch job that ran 11 minutes ago. Monitoring told you something was wrong. Observability would have told you what. This is not a semantic argument. Teams with mature observability resolve incidents 2.8x faster than teams that rely on monitoring alone, according to DORA research. The gap matters in production. Understanding why the gap e
Knowledge Map
Connected Articles — Knowledge Graph
This article is connected to other articles through shared AI topics and tags.
More in Products

Behavior is the New Credential
We are living through a paradigm shift in how we prove we are who we say we are online. Instead of asking What do you know? (password, PIN, mother’s maiden name) or What do you look like? (Face ID, fingerprint) the question has become How do you behave? The post Behavior is the New Credential appeared first on Towards Data Science .

QUANTUM HORIZONS Your Passwords Have an Expiry Date. Nobody Told You.
By The Architect NEO | April 2026 You know that friend? The one at every barbecue who, somewhere between the third burger and the dying embers, starts talking about encryption? The one who makes you check if your webcam has tape over it? The one who said "don't use that free Wi-Fi" at the airport in 2019 and you thought they were being dramatic? That friend was right about everything. And they're about to be right again — about something much, much bigger. THE QUIET HEIST NOBODY'S REPORTING Right now, while you're reading this on a Tuesday lunchbreak or doomscrolling at 11pm, encrypted data is being stolen. Not decrypted. Not read. Not yet. Stored. Intelligence agencies across the globe have a name for it: "Harvest Now, Decrypt Later." The idea is brutally simple. Steal encrypted data toda

Cloud Cost Anomaly Detection: How to Catch Surprise Bills Before They Hit
Cloud Cost Anomaly Detection: How to Catch Surprise Bills Before They Hit Cloud bills don't spike gradually. They spike overnight. A misconfigured NAT gateway starts routing all inter-AZ traffic inefficiently on a Friday. A data pipeline job enters an infinite retry loop on Saturday. A developer spins up a p3.8xlarge for a test and forgets to terminate it over a long weekend. By the time you find out, you've already burned through budget that wasn't allocated for it. The problem isn't that anomalies happen. The problem is the detection lag: most teams don't discover a cost spike until the invoice arrives 30 days later. With the right alerting in place, you catch the same spike in under 6 hours. This is the practical guide to setting that up. Why Cloud Bills Spike (And Why You Don't Find Ou


Discussion
Sign in to join the discussion
No comments yet — be the first to share your thoughts!