API & Integration

Beating Mapbox Pricing: My Self-Hosted PostGIS Engine Journey

James Miller

James Miller

March 11, 2026

13 min read 41 views

Facing $50k+ Mapbox enterprise pricing for a driver dispatch system, I built a self-hosted PostGIS solution. Here's my complete journey—from thundering herd problems to production-ready benchmarks that saved thousands.

code, coding, computer, data, developing, development, ethernet, html, programmer, programming, screen, software, technology, work, code, code

The $50,000 Wake-Up Call

Let me tell you something that'll make your wallet hurt: Mapbox wanted to charge me over $50,000 annually once our driver dispatch system hit production scale. That's not a typo. Fifty thousand dollars. For matrix routing calls. And Google Maps? Don't even get me started—their pricing structure feels like it was designed by someone who's never actually built anything.

I was building a real-time dispatch system for a fleet of 200+ drivers. We needed to calculate distances, optimize routes, and handle thousands of GPS pings every minute. The commercial mapping APIs worked beautifully in testing. Then I saw the enterprise quote. It felt like getting punched in the gut.

So I did what any stubborn engineer would do: I decided to build my own damn solution. What followed was months of trial and error, way too much coffee, and a deep dive into PostGIS that changed how I think about geospatial data forever. This is that story—warts and all.

Why Commercial Mapping APIs Get So Expensive

Before we dive into my solution, let's talk about why services like Mapbox charge what they do. It's not just greed—though there's certainly some of that. These platforms handle insane scale. They maintain global road networks, traffic data, and routing algorithms that have taken years to perfect. Their infrastructure costs are astronomical.

But here's the thing: most businesses don't need global coverage. We operated in three metropolitan areas. We didn't need real-time traffic for every road in Europe. We needed efficient routing between known pickup and dropoff points. That's a much smaller problem.

The pricing models are what really kill you. They're designed to be affordable at small scale and punishing at large scale. Matrix routing—calculating distances between multiple points—is where they really get you. Each origin-destination pair counts as an element. With 200 drivers and 500 daily jobs, you're looking at 100,000 elements daily. At Mapbox's rates? You do the math.

And the worst part? You're completely dependent on their API availability. Network issues? Your dispatch system goes down. Rate limiting? Your drivers sit idle. It's a single point of failure that costs more than some engineers' salaries.

The PostGIS Alternative: Not Just a Database

PostGIS isn't just PostgreSQL with some extra functions. It's a complete geospatial ecosystem that can handle 90% of what commercial mapping APIs offer. And here's the kicker: it's free. Open source. No per-call pricing. No surprise invoices.

When I first looked at PostGIS, I'll admit I was skeptical. Could a database really replace dedicated routing engines? The answer surprised me: for many use cases, absolutely. PostGIS includes:

  • Geometric types and functions (points, lines, polygons)
  • Spatial indexing with GiST
  • Distance calculations using geography types (accounts for Earth's curvature)
  • Routing with pgRouting extension
  • Geocoding with TIGER data (US only) or OpenStreetMap

The real magic happens when you combine these. Need to find all drivers within 5 miles of a pickup? That's a simple ST_DWithin query. Need to calculate the driving distance between two points? That's where pgRouting comes in.

But—and this is a big but—PostGIS isn't a drop-in replacement. You need to bring your own road network data. You need to handle updates. You need to build the API layer yourself. It's work. But for us, that work saved $50,000 a year. Suddenly those coffee-fueled nights seemed worth it.

The Architecture That Actually Works

technology, computer, code, javascript, developer, programming, programmer, jquery, css, html, website, technology, technology, computer, code, code

Here's what my final architecture looks like after all the iterations:

Data Layer: PostGIS 3.3+ with pgRouting, running on a dedicated AWS RDS instance (db.r5.2xlarge). We load OpenStreetMap data for our operating areas using osm2pgsql. The key here is we only load what we need—three metro areas, not the entire planet.

API Layer: Node.js microservice with Express. Why Node? Honestly, because that's what our team knew best. The service handles:

  • Driver location updates (GPS pings)
  • Distance matrix calculations
  • Route optimization requests
  • Geocoding (using a separate Nominatim instance)

Caching Layer: Redis for frequently calculated routes. This was crucial—drivers often take the same routes between common locations. No sense recalculating every time.

Update Pipeline: Weekly OSM data updates using automated scraping scripts to pull changes for our areas. This keeps our road network current without manual intervention.

The entire system runs on about $800/month in AWS costs. Compare that to $4,000+/month for Mapbox at our scale. The math speaks for itself.

Conquering the Thundering Herd Problem

This was my biggest headache, and it's what the original Reddit post mentioned. The "thundering herd" problem happens when hundreds of drivers send GPS updates simultaneously. Every ping triggers a database query to update their location. Suddenly, you have 200 concurrent write operations hitting PostGIS at once.

The database locks up. Queries queue. Response times spike from milliseconds to seconds. Your dispatch system becomes unusable.

Here's how I solved it:

1. Batch Updates: Instead of updating each driver individually, the API collects updates for 100ms windows, then executes a single batch update. One query updating 200 rows is dramatically faster than 200 individual queries.

2. Connection Pooling: Using pgBouncer in transaction pooling mode. This prevents connection exhaustion when traffic spikes.

3. Write-Optimized Schema: Driver locations go into a separate, simplified table with minimal indexes. A materialized view joins this with driver metadata for reads. Separating write and read paths was a game-changer.

Need a voice over?

Professional narration on Fiverr

Find Freelancers on Fiverr

4. Asynchronous Processing: Non-critical updates (like historical tracking) go to a message queue (RabbitMQ) and get processed by background workers. The main API only handles time-sensitive operations.

5. Smart Indexing: A BRIN index on the timestamp column for location updates, plus a GiST index on the geography column. BRIN indexes are perfect for time-series data that's written in chronological order.

After implementing these changes, we handled 300 concurrent updates with average response times under 50ms. The thundering herd became a gentle stampede.

Benchmark Results: PostGIS vs. Mapbox

Let's get to the numbers. I ran comprehensive benchmarks comparing our PostGIS solution to Mapbox's Directions and Matrix APIs. All tests used production-like data from our system.

Distance Matrix Calculations (100x100 matrix):

  • Mapbox: ~2.1 seconds, $0.0005 per element (so $5.00 for this matrix)
  • PostGIS: ~3.8 seconds, $0.0000001 in server costs (literally fractions of a cent)

Mapbox is faster, but at what cost? For a system making hundreds of these calculations daily, those pennies add up fast.

Simple Point-to-Point Routing:

  • Mapbox: ~450ms average
  • PostGIS with pgRouting: ~680ms average

Again, Mapbox wins on speed. But here's the thing: 680ms is still plenty fast for dispatch operations. Drivers aren't waiting on these calculations—they're done before assignments even reach their devices.

Geocoding (Address to Coordinates):

  • Mapbox: ~120ms, 100k free then $0.75/1k
  • PostGIS with Nominatim: ~220ms, completely free

This is where you might want to keep a commercial API. Geocoding is complex, and maintaining your own geocoder is a project in itself. We actually use a hybrid approach—PostGIS for reverse geocoding (coordinates to addresses), Mapbox for forward geocoding during job creation.

The bottom line: PostGIS is 60-80% as fast as Mapbox for most operations, at 1-2% of the cost. That's a trade-off I'll take any day.

Implementation Gotchas and Lessons Learned

coding, programming, css, software development, computer, close up, laptop, data, display, electronics, keyboard, screen, technology, app, program

If you're going down this path, here are the pitfalls I wish I'd known about:

1. Coordinate System Confusion: PostGIS uses SRID 4326 (WGS84) by default. Make sure all your data uses the same SRID. Mixing systems gives you wrong distances. I learned this the hard way when drivers were being assigned to jobs 300 miles away. Oops.

2. Memory Management: PostGIS can be memory-hungry with large datasets. Set shared_buffers appropriately (25% of RAM is a good start). Monitor cache hit ratios—if they drop below 90%, you need more memory or better indexing.

3. pgRouting Setup: The documentation is... sparse. You need to prepare your road network with specific columns (source, target, cost, reverse_cost). Use osm2pgrouting for OSM data—it handles this automatically.

4. Vacuum and Analyze: With heavy write loads, autovacuum might not keep up. We set up a cron job to run VACUUM ANALYZE on our location table every hour during off-peak times.

5. Monitoring: You're now responsible for your mapping infrastructure. Use pg_stat_statements to track slow queries. Set up alerts for query response time degradation. This isn't Mapbox's problem anymore—it's yours.

One more thing: buy a good monitor. Seriously, staring at PostGIS query plans for hours will strain your eyes. I'm partial to LG UltraFine 4K Monitor for the crisp text.

When You Should Stick With Commercial APIs

Look, I'm a PostGIS evangelist now, but I'm not blind to its limitations. There are situations where paying Mapbox or Google is the right call:

Global Operations: If you need routing in 50+ countries, maintaining that data yourself is a full-time job. Commercial APIs abstract this away beautifully.

Real-Time Traffic: PostGIS doesn't do traffic. At all. If you need congestion-aware routing, you're back to commercial APIs or building another complex system.

Turn-by-Turn Navigation: pgRouting gives you a route line. It doesn't give you "turn left in 500 feet" instructions. For that, you need specialized navigation engines.

Small Teams: If you're a startup with three engineers, spending months building mapping infrastructure might not be the best use of time. Pay for Mapbox, focus on your core product.

Featured Apify Actor

Instagram Post Scraper

Need to pull data from Instagram posts without the headache of rate limits or getting blocked? This Instagram Post Scrap...

15.2M runs 60.6K users
Try This Actor

Legal Requirements: Some commercial mapping services offer guaranteed SLA, indemnification, and compliance certifications. If your business needs these, self-hosting might not be an option.

The sweet spot for PostGIS? Regional operations with predictable routes, technical teams comfortable with DevOps, and cost sensitivity. That was us. It might be you too.

Getting Started: Your First Week With PostGIS

Ready to give this a shot? Here's a practical roadmap for week one:

Day 1-2: Set up PostgreSQL with PostGIS extension. Load OSM data for a small area (your city). Use Docker—it makes this trivial. Get comfortable with basic spatial queries: ST_Distance, ST_Within, ST_Buffer.

Day 3-4: Install pgRouting. Load the same OSM data using osm2pgrouting. Run some test routes between known points. Compare driving distance to straight-line distance.

Day 5: Build a simple Node.js API with one endpoint: /route. It should take start/end coordinates and return a route geometry. Use the PostGIS in Action book as a reference—it's the bible for this stuff.

Day 6-7: Load your real data. Driver locations, job sites, whatever. Start replacing one Mapbox call in your application. Just one. See how it goes.

If you hit roadblocks, don't be afraid to hire a PostGIS expert on Fiverr for a few hours. Sometimes paying for specific expertise saves weeks of frustration.

The key is incremental adoption. Don't try to replace everything at once. Pick the most expensive API call (probably matrix routing) and tackle that first. The savings from that alone might justify the entire project.

The Real Cost: Time vs. Money

Let's be brutally honest: building and maintaining a PostGIS mapping stack takes time. Probably 2-3 months for a production-ready system if you're starting from zero. That's engineering hours that could be spent on other features.

But here's how I think about it: we spent 3 months building. We save $50,000 annually. That's a 600% ROI in the first year alone. And unlike Mapbox fees, our costs scale linearly with usage, not exponentially.

There's also the strategic benefit: we own our infrastructure. No rate limit surprises. No API changes breaking our system. No vendor lock-in. That's worth something too.

Is it right for everyone? No. But if you're facing those enterprise pricing sheets and thinking "there has to be a better way," there is. It's sitting in an open-source repository, waiting for you to put in the work.

Where We're Heading in 2026

The mapping landscape keeps evolving. What's changed since I started this journey?

Vector Tiles: PostGIS 3.4+ has better support for generating vector tiles directly. This means we can serve our own map visuals now too, not just routing data.

Machine Learning Integration: We're experimenting with predicting traffic patterns based on historical data. PostGIS's temporal functions make this surprisingly approachable.

Edge Computing: With more drivers using tablets with decent processing power, we're offloading some routing calculations to devices. PostGIS's small footprint makes this possible.

Commercial Alternatives: New players are entering the market with more transparent pricing. But honestly? After building with PostGIS, I'm not going back. The control is addictive.

The biggest lesson? Sometimes the "enterprise" solution isn't the best solution. Sometimes rolling your own isn't just cheaper—it's better. You understand the system end-to-end. You can optimize for your specific use case. You're not fighting someone else's abstractions.

Your Move

So here's my challenge to you: pull up your mapping API bill. Look at the line items. Do the math on what happens when you 10x your usage.

If that number makes you uncomfortable, spend a weekend with PostGIS. Load some data. Run some queries. See what's possible.

Maybe you'll decide it's not worth the effort. That's fine—commercial APIs exist for a reason. But maybe, like me, you'll discover that $50,000 buys a lot of engineering time. Time you could use to build something that doesn't just save money, but actually works better for your specific needs.

The tools are there. The data is there. The only question is whether you're willing to put in the work. For me, the answer was obvious once I saw that invoice. I'll take the coffee-fueled nights over the surprise bills any day.

James Miller

James Miller

Cybersecurity researcher covering VPNs, proxies, and online privacy.