Having recently concluded a multi-vendor evaluation for a consolidated observability platform at my organization, I found myself drowning in a sea of vendor-provided quotes, each with its own unique formatting, unit of measurement, and pricing model. The process of performing an apples-to-apples comparison was becoming a project in itself. To bring order to this chaos, I built a detailed spreadsheet template, which I've now refined and sanitized for public use.
The core challenge is that vendors present costs differently. Some lead with data ingestion per GB, others with per-million time series samples, and yet others with user-based seats. To compare them, you must normalize all inputs to a common projected workload. My template enforces this discipline.
**Key Inputs & Normalized Calculations:**
* **Baseline Workload:** You define your estimated monthly volumes (e.g., 10 TB logs, 2 TB metrics, 1 TB traces).
* **Ingestion Normalization:** The template converts all vendor quotes—whether priced by GB, by million events, or by million samples—into a cost per GB ingested for each telemetry type.
* **Retention & Query Tiers:** It separately calculates costs for different retention periods (hot, warm, cold) and any associated query costs.
* **Commit & Overages:** Models the financial impact of committed-use discounts versus pay-as-you-go, and charts overage costs.
* **Ancillary Costs:** Factors in per-user pricing, support tiers, and costs for essential features like SSO, external alerting, or data egress.
Here is a simplified view of the core calculation engine's logic for metrics ingestion, which is often the most complex to compare:
```plaintext
Vendor A Quote: $0.50 per million samples ingested (1 sample = 1 metric at 1 timestamp).
Our Projection: 50,000 unique metrics, 30-second resolution, 30-day month.
Step 1: Calculate total monthly samples.
Samples per metric per month = (86400 seconds/day / 30-second interval) * 30 days = 86,400
Total samples = 50,000 metrics * 86,400 samples = 4,320,000,000 samples
Step 2: Normalize to vendor's pricing unit.
Vendor A units = 4,320,000,000 samples / 1,000,000 = 4,320 million-sample units
Step 3: Calculate cost.
Raw Ingestion Cost = 4,320 units * $0.50/unit = $2,160
Step 4: Normalize to cost per GB (for cross-vendor comparison).
Assumed average bytes per sample (e.g., 100 bytes) = 4,320,000,000 samples * 100 bytes = 432 GB
Normalized Cost per GB = $2,160 / 432 GB = $5.00/GB
```
This normalized figure can then be directly compared to Vendor B, who might quote a straightforward $2.50/GB for metrics ingestion, revealing a significant cost difference that the raw quotes obscured.
**Lessons Learned & Template Features:**
* **Cardinality is a Silent Killer:** The template forces you to input your estimated unique time series count. Platforms with high per-series costs can explode your bill if you have high cardinality, even at modest data volumes.
* **Query Patterns Matter:** If your team runs frequent, broad queries, a platform charging per query scan can become more expensive than one with a higher ingestion cost but unlimited queries.
* **The Total Cost of Ownership (TCO) View:** The final output is a dashboard that summarizes not just ingestion, but the total monthly and annual cost for each vendor, incorporating all the layered costs. It visualizes the inflection points where one vendor becomes cheaper than another as your workload scales.
I am sharing this template not as a definitive answer, but as a rigorous framework for analysis. Blindly trusting a vendor's "cost calculator" often leads to unpleasant surprises. This method requires more upfront work to model your workload, but it pays dividends in negotiation and long-term budget predictability. You can find a link to the template [in my public repository](link_placeholder). I welcome suggestions for additional factors to model—have you encountered other hidden costs during your evaluations?
That normalization step is so crucial, and something most people gloss over until they get the first bill. I've been burned before by a quote that looked amazing on per-sample pricing, but our workload was actually far heavier on logs. Converting everything to a cost per GB for each data type exposed that instantly.
Would love to see how you handle committed use discounts or tiered pricing where the per-unit cost drops at volume. Those can really warp the final numbers if you're not careful.
Are you factoring in egress or API call costs for querying? That's another sneaky one that can pop up, especially if you have analysts running a lot of exploratory queries.
cost first, then scale
Ah, the classic 'per-sample pricing looks great until you realize your data isn't samples.' Been there, got the t-shirt and the unexpectedly large invoice. Your point about logs versus metrics is exactly why these spreadsheets, while necessary, are just the starting pistol for a much longer race.
The real fun begins when you try to model those tiered pricing and committed use discounts. Most templates, and frankly most finance teams, assume a linear cost model. They'll take your projected volume and multiply. But if the discount kicks in at 15% above your projection, you're either leaving money on the table or your 'apples-to-apples' comparison is now comparing a firm apple to a theoretical, cheaper apple you might get next quarter. You have to build multiple scenarios - steady state, optimistic growth, and 'what if we're wrong' - which vendors are notoriously reluctant to help you model.
And don't get me started on egress and API costs. That's not a sneaky line item, that's the entire business model for some platforms. They hook you on cheap ingestion and then charge you every time you want to actually use your own data. A template that doesn't force you to estimate query patterns and data export volumes is just comparing the bait, not the trap.
Test the migration.
This is such a smart approach. The **Ingestion Normalization** step is exactly where most comparisons fall apart. I'd add one thing to watch for: data compression ratios.
Vendor A might quote $1 per ingested GB, but if their agent applies heavy compression, you're actually sending them 3GB of raw data. Vendor B quotes $0.80 per GB with light compression. Suddenly the 'more expensive' vendor is cheaper for your actual workload. The template forces you to ask that question upfront, which is huge.
Have you built in a cell to note each vendor's stated compression or reduction factor? That can flip the whole model on its head.
Automate all the things
The retention tier separation is a smart move. It's a common oversight to treat all stored data as a single cost pool.
A practical challenge with retention costing is the data lifecycle. For example, moving data from a hot query tier to a long-term archive often isn't a simple per-GB shift. Some platforms charge a retrieval fee to query archived data, while others bake the archive cost into a higher ingestion price. Does your template have a way to capture that retrieval cost or the operational latency of accessing colder tiers? That can significantly impact the total cost of ownership if teams need to query historical data regularly.
CloudCostHawk
Normalizing ingestion to a cost per GB for each data type is the only way to get a real comparison. I've seen teams get quotes for "per-host" pricing and then realize their auto-scaling group varies from 10 to 200 instances daily.
One column I always add is for estimated annual growth. A vendor's pricing might be best for your 10TB baseline, but if you're growing at 40% year-over-year, their steep volume tier jumps could make them the most expensive option by year two. Does your template have a row to model that growth and see where you hit the next pricing tier?
The separate retention & query tier costing is a great call. I'd add that you need to track if the *query* pricing is tied to the same tier. Some vendors charge more to query data in the 'hot' tier versus the 'cold' archive, even if you're already paying more to store it there. It's like paying for premium parking and then an extra fee to actually get in your car.
Also, how does the template handle vendors that bundle a query allotment into the ingestion price? That's a common trick. A higher per-GB cost might include 100 queries, while the cheaper one charges per query after the first 10. You need a column for estimated monthly queries to make those models truly comparable.
Still looking for the perfect one
You're absolutely right about query pricing being tied to storage tiers, it adds a frustrating layer of complexity. I've seen this with data lake query engines, where scanning cold storage incurs a separate compute fee on top of the storage cost.
For bundled query allotments, my template has a separate section for "Included Usage" where you can note the free query count. The key is linking it to the "Estimated Monthly Queries" input. The model then calculates the overage cost if your estimate exceeds the bundle. The trap is when vendors count different query types - a simple filter versus a full table scan - as the same unit. That needs a manual footnote.
terraform and chill
The footnote for query types is the whole ballgame. You can't just take their quoted 'query count' at face value because every vendor's definition is a completely bespoke black box designed to look favorable. Vendor A calls a filtered search on indexed fields a 'query', while Vendor B only counts a 'query' when you perform a full aggregation scan. Your bundled 100 queries could be exhausted in a week or last a year, and you won't know until you're building the report.
That separate compute fee for cold data is the ultimate rug pull. It turns the supposed savings of archival storage into a cost center the moment anyone needs to look at last quarter's numbers. You're not just paying for the storage, you're paying a toll to remember anything. It effectively makes historical data too expensive to use, which defeats the entire point of buying an observability platform.
Modeling that requires forecasting not just how much you'll store, but how often you'll actually need to go back and touch it. Good luck getting that estimate from engineering.
You nailed it. The separate compute for cold data is what makes 'cheap storage' a bait and switch. We had to build a query audit into our log pipeline just to model this. Every dashboard, every alert, every post-mortem query against old data gets logged with a data source tag. That gave us real numbers on how often we actually queried beyond 30 days.
It turned out "cheap storage" was 300% more expensive over three years because our SREs query historical data constantly. You can't trust a vendor's pricing page, you have to trace your own access patterns.
shift left or go home
That normalization step is critical, and I love that you've split out retention and query tiers. I've seen too many models collapse because they just multiplied total storage by a single cost.
One thing I'd add - make sure you're projecting volume per data type separately. A vendor with cheap logs but expensive traces might look great if you just use an "overall" GB estimate, but terrible if you're heavy on APM. Your baseline workload section probably covers this, but it's worth double-checking those splits.
Any chance you're sharing the template? I've got a colleague about to start this process and I'd love to save them the headache.
Dashboards or it didn't happen.
The baseline workload step is the most critical part of this exercise, and it's also the easiest to get wrong if you don't have historical data. People consistently underestimate their true volume, especially for traces and high-cardinality metrics.
Your ingestion normalization column is a good start, but it misses a key operational factor for metrics: cardinality. Two vendors might quote the same price per million time series samples, but Vendor A's counting methodology might bill you for 10x the samples due to how they handle high-cardinality dimensions. You need a footnote to document each vendor's sample definition, or your normalized cost per GB will be off by an order of magnitude. I've seen this trap catch teams who move from a simple host-based metric system to something more granular.
null