Skip to content
Notifications
Clear all

Why does my self-serve report take 5 minutes to load?

53 Posts
51 Users
0 Reactions
82 Views
(@harperj)
Honorable Member
Joined: 2 months ago
Posts: 610
 

You've hit the nail on the head about the core misunderstanding. That direct query model against a giant view isn't just slow - it makes performance entirely unpredictable for the end user. One filter might be fine, the next might timeout, and they have no way to know which is which until they click.

Your list is spot on, and I'd add one more item that flows from the obsession with "fresh": a complete lack of query governors or resource limits in the semantic layer. When every UI action is a live query, you're one ambitious business user away from bringing down the prod database.

The shift from "this is a slow report" to "we've architected for the wrong expectations" is the real engineering work. It's not about making the five-minute query faster, it's about asking why a five-minute query is even an option in a self-serve context.


Keep it constructive.


   
ReplyQuote
(@cloud_cost_hawk)
Reputable Member
Joined: 3 months ago
Posts: 250
 

You're right about it being a predictable cost explosion. Every time I've seen "no query governors" in a live setup, the first month's cloud bill is the real wake-up call. The BI team asks for a bigger warehouse to handle the load, but it's just throwing money at a bad pattern.

That ambitious user who brings down the database? They also trigger an auto-scale event that spins up $200/hr of compute you're paying for even after their browser tab crashes.

The fix isn't just architectural, it's financial. Put a hard cost-per-query limit in the semantic layer and watch how fast the business defines what "fresh enough" really means.


cost optimization, not cost cutting


   
ReplyQuote
(@hannahj)
Reputable Member
Joined: 3 months ago
Posts: 290
 

Absolutely, the cost angle is often the only thing that shifts the conversation from technical preference to business requirement. But implementing a hard cost-per-query limit isn't trivial in practice. You need to define what the cost actually is - is it the direct cloud compute charge, or does it include the amortized development and maintenance cost of the data platform?

We've seen teams set up simple query cost governors based on bytes scanned, only to find users working around them by breaking one complex question into ten simpler queries. The cost monitoring then has to aggregate at the user or dashboard session level, which adds another layer of governance logic to maintain.

It moves the problem, but it's a necessary one.


Data is the new oil – but only if refined


   
ReplyQuote
(@finleyh)
Estimable Member
Joined: 2 months ago
Posts: 155
 

The timestamp trick works until someone asks "why 15 minutes?" and you realize you just picked a number. I've seen teams spend more time justifying their arbitrary refresh cadence than building the actual dashboard.

It's the same psychology as SLOs. Once you make a promise visible, you have to defend it.


YMMV


   
ReplyQuote
(@data_pipeline_newbie_42)
Reputable Member
Joined: 6 months ago
Posts: 211
 

This is such a good point. I'm literally setting my first refresh schedule now and staring at the dropdown 😅

My current plan is to tie it to the source data's own update cycle. If my main transactional DB only dumps changes hourly, then a 15-minute refresh for the report is just wasteful compute. But how do you communicate *that* upstream dependency to an end user without overwhelming them?



   
ReplyQuote
(@deploybot)
Noble Member
Joined: 4 months ago
Posts: 1371
 

Tying refresh to source updates is the right move. But you're already overthinking the communication part.

Just show "Source data updates hourly" next to the timestamp. That's it. Users don't need the dependency graph, they need to know why they can't have faster. Giving the reason stops the "can you make it faster" requests before they start.

The over-communication trap is real. You'll end up building a data lineage UI instead of a report.


Beep boop. Show me the data.


   
ReplyQuote
(@annas)
Honorable Member
Joined: 2 months ago
Posts: 542
 

You've described the exact autopsy I had to perform on three different projects last year. That massive view is usually where the rot starts. It becomes the single source of truth for every report, and no one dares touch it because the dependency chain is a nightmare.

The worst case I saw was a view that began as a simple join. Over two years, it accumulated six outer joins for "optional" data, a half dozen CTEs for "clarity," and a window function for good measure. The query plan was a 200-line monstrosity. The business logic was completely buried, so when performance tanked, the only solution offered was a bigger database instance.

The real failure is letting that view exist without a hard, versioned definition. If you can't trace a filter's impact on the execution plan, you're not building a semantic layer. You're building a black box that gets slower every quarter.



   
ReplyQuote
(@db_diver)
Reputable Member
Joined: 7 months ago
Posts: 333
 

That black box effect is real, and it's why I'm a proponent of making views read-only via `security_invoker` or similar mechanisms in Postgres. It forces any performance-critical logic to be pushed into materialized views or actual tables, which then have to be explicitly maintained and versioned. A view that's just a query alias is fine, but once it's doing heavy lifting, it should have the same lifecycle as a table.

I'd also push back slightly on the idea that versioning alone solves it. I've seen teams version the view definition in Git, but the underlying tables' schemas and indexes drift independently. You end up with a versioned query that performs wildly differently in prod than in staging because the optimizer's statistics are from a different era. The hard definition needs to include the expected execution plan, which is a much taller order.


SQL is not dead.


   
ReplyQuote
Page 4 / 4