I Built a Cloud Pricing Comparison Tool
I hadn’t touched Rails in over six years. The last time I wrote Ruby professionally, Rails 5 was the new hotness and Webpacker was the future. I wanted an excuse to come back to it and see how the framework has evolved — so I gave myself a project that would actually be useful.
The result is CloudPricing, a tool that pulls live on-demand pricing from AWS, Azure, and GCP into one searchable, sortable table.
The Problem
Every cloud provider publishes their pricing differently:
- AWS has a massive JSON file (~1GB) with every SKU buried under product attributes and pricing dimensions
- Azure has a paginated REST API with its own filter syntax
- GCP doesn’t even price per-instance — they charge per-vCPU-hour and per-GB-RAM-hour, so you have to do math to get a comparable number
If you just want to know “what’s the cheapest 8-vCPU box across all three providers,” good luck doing that quickly.
How It Works
The app has three importers, one per provider. Each pulls data from the provider’s pricing API and normalizes it into a common schema: instance type, vCPUs, memory, hourly price, region, and family.
AWS is the most straightforward — their bulk pricing JSON includes everything. Filter for Linux, shared tenancy, on-demand, us-east-1, and you get ~1,174 instances.
Azure has a clean REST API at prices.azure.com. Filter by region, service, and consumption pricing, then paginate through the results. That gives ~1,582 instances.
GCP was the tricky one. Their old pricing calculator JSON endpoint (cloudpricingcalculator.appspot.com) is dead — returns 404. The replacement is the Cloud Billing Catalog API, which gives you per-component rates (CPU and RAM separately) for each machine family. I fetch those rates, then calculate per-instance prices using known vCPU/memory specs for each machine type. The result: 96 instances across 7 machine families.
All told, the app indexes 2,852 instances that you can filter by provider, vCPU range, memory range, and family.
The Stack
- Rails 7 with Hotwire/Turbo for snappy filtering without full page reloads
- Postgres for the instance data
- Pagy for pagination
- Chartkick + Chart.js for scatter plots and bar charts
- Tailwind CSS for styling
- Docker Compose for deployment on my Hetzner VPS
The whole thing runs alongside my other projects on the same $5/mo box. Caddy handles HTTPS, Docker keeps it isolated, and the pricing data refreshes via a rake task.
Coming Back to Rails
The Rails ecosystem has changed a lot since I last used it. Webpacker is gone, replaced by importmap — no Node, no bundler, just ES modules served directly. Hotwire and Turbo handle the kind of interactivity that used to require a React frontend. The filters on the main table submit via Turbo Frames, so filtering 2,800+ instances feels instant without writing a single line of JavaScript for data fetching.
Honestly, it felt like coming home. Rails is still opinionated in the right ways, and the new defaults (propshaft, importmap, Turbo) strip away a lot of the complexity that had crept in during the Webpack era. If you’ve been away for a while, it’s worth a look.
What I’d Add Next
- More regions — right now it’s us-east-1 (AWS), eastus (Azure), and us-central1 (GCP)
- Reserved/spot pricing — on-demand is just one piece of the puzzle
- Price history — track how rates change over time
- DigitalOcean/Hetzner — the smaller providers deserve a seat at the table
Check it out at cloudpricing.buford.dev. The source is on GitHub.