Skip to content
Notifications
Clear all

What's the best way to track costs for a multi-tenant SaaS application?

6 Posts
6 Users
0 Reactions
1 Views
(@data_analytics_rover)
Reputable Member
Joined: 4 months ago
Posts: 161
Topic starter   [#21841]

I'm analyzing cost allocation for a multi-tenant SaaS product built on Snowflake and BigQuery. The core challenge is moving from aggregate cloud bills to accurate per-tenant P&L, especially with shared infrastructure like processing pipelines and materialized views. Tagging at the cloud provider level feels insufficient.

Our current approach uses a combination of platform-native tagging and query-level instrumentation:

* **Infrastructure Tagging:** All compute resources (e.g., Snowflake warehouses, BigQuery reservation slots) are tagged with `tenant_id: shared`. This captures the base cost.
* **Query-Level Attribution:** We've implemented a middleware layer that injects `tenant_id` into the session context for every query. In dbt, we use a similar pattern via `set` commands in the `dbt_project.yml`. This allows us to join with query history logs.

```sql
-- Example from our Snowflake instrumentation
ALTER SESSION SET user_defined_tenant_id = 'tenant_abc123';
SELECT * FROM analytics.fct_orders;
```

We then join `SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY` with the session context to allocate compute costs. Storage costs are prorated based on table row counts partitioned by tenant.

The unresolved pain points:
1. **Noisy Neighbors:** A single large tenant can spike costs for everyone on shared compute. Our attribution is accurate, but doesn't enable per-tenant cost *control*.
2. **ETL Overhead:** Cost attribution for our dbt transformation jobs is still manual. We have to parse the compiled SQL to map model runs back to tenant datasets.

I'm evaluating whether to move to a fully isolated warehouse-per-tenant model, but the overhead seems high. Has anyone built a robust system that provides both accurate attribution and the levers to control spend per client? Concrete numbers on the percentage of overhead for isolation vs. sharing would be particularly valuable.



   
Quote
(@carlr)
Estimable Member
Joined: 2 weeks ago
Posts: 104
 

Infrastructure lead at a B2B SaaS in logistics, ~200 employees. Our analytics stack runs on Snowflake and BigQuery with dbt, serving ~150 distinct tenants. We went through this exact cost attribution grind two years ago and now run a homegrown allocation system in production.

**Core Comparison**

* **Integration Effort**: Instrumenting queries via session context, as you've done, is the minimum viable lift. The real effort is building and maintaining the allocation pipeline itself. Expect 2-3 months of engineering time for a stable system that joins provider billing data with your usage logs, handles proration for shared storage/warehouses, and surfaces tenant-level dashboards.
* **Accuracy vs. Granularity**: Your query-level approach will get you to about 85-90% accuracy for compute. The gap is idle warehouse costs and shared processing (like a materialized view that refreshes data for all tenants). We prorate these shared overheads based on each tenant's percentage of total query cost over the period, which is defensible for internal P&L but not for actual tenant billing.
* **Ongoing Maintenance Burden**: The pipeline is brittle. Every change in your data platform's query logging schema or your own orchestration tool (like dbt version upgrades) risks breaking attribution. We dedicate roughly one eng day per month to maintenance and edge-case handling.
* **Cost of the Solution Itself**: Building it costs engineering salary. Hosting it costs compute. Our allocation pipeline runs as a weekly Airflow DAG on a mid-sized BigQuery flat-rate reservation, which adds about $1.2k/month to the very bill we're trying to dissect. Third-party SaaS tools in this space (like CloudTruth, Tangoe) typically start at $15k/year and scale from there, but they often rely on the same tagging fundamentals.

**My Pick**

I'd recommend you double down on your custom build, because you've already done the hard part with session instrumentation. For accurate internal chargeback and identifying outlier tenants, it's sufficient. If you need line-item invoicing for clients or are in a heavily regulated industry, you need a commercial tool. Tell us if this is for internal finance or external billing, and your annual analytics spend. If it's over $500k, the commercial tool ROI becomes plausible.


Your fancy demo doesn't scale.


   
ReplyQuote
(@backend_perf_guru)
Reputable Member
Joined: 5 months ago
Posts: 171
 

You're on a solid path, but that session context method has a critical edge case - it's lost if a query uses a result cache. A cached query in Snowflake won't trigger a warehouse spin-up, so its cost isn't in QUERY_HISTORY, but your allocation logic might still assign the base warehouse cost to the tenant who first ran it. We had to implement a separate audit for cache hit rates and adjust allocations pro-rata.

Your storage proration by row count is also sensible, though it breaks down if you have significant variance in row size across tenants. We ended up sampling actual compressed byte counts per tenant partition periodically instead.


--perf


   
ReplyQuote
(@grace5)
Trusted Member
Joined: 2 weeks ago
Posts: 46
 

That's a really clever approach, using the session context to tag queries. It seems much cleaner than trying to parse SQL comments or modify application logic.

I'm curious about how you handle the allocation for shared materialized views or pipelines that refresh data for all tenants. Do you split that cost evenly, or is there a way to attribute it based on downstream query activity? I'm thinking of our nightly dbt models that build a core table used by everyone.



   
ReplyQuote
(@emilyc)
Trusted Member
Joined: 2 weeks ago
Posts: 41
 

Great question! That's the exact part that makes my head spin a bit too. Splitting shared pipeline costs evenly feels wrong if some tenants use the results way more than others, but tracking downstream usage gets so complex.

In a basic GA setup I've used, you could maybe attribute based on how many times each tenant's users triggered a report that depends on that core table? But that's a whole other layer of logging. 😅

Is there a simpler heuristic you've seen work, like weighting by tenant revenue or active users?



   
ReplyQuote
 danw
(@danw)
Estimable Member
Joined: 2 weeks ago
Posts: 79
 

Weighting by revenue is the pragmatic answer here, but it's an accounting choice, not a technical one. You're not allocating actual cost, you're assigning overhead.

The simpler heuristic is to treat shared pipeline costs as a fixed platform cost and absorb it. If you must allocate, do it by tenant revenue percentage. It directly ties cost to business value and changes slowly enough to be manageable. Tracking downstream usage is a rabbit hole that rarely pays off.



   
ReplyQuote