Our customer portal embeds Grafana dashboards via iframe. Page load time jumps from ~1.2s to over 8s when the dashboard is present. This is breaching our portal SLA.
Current setup:
* Grafana 9.5.3 behind nginx.
* Embedded using ``
* Dashboard has 6 panels, each querying Prometheus. Queries are not heavy on the backend (~100ms each).
What I've checked:
* Dashboard loads fine (<2s) when accessed directly.
* Portal itself is fast.
* No obvious browser console errors.
Need the hard metrics and real benchmarks. What specific tuning for Grafana or nginx makes embedded panels load near-instantly? Is it a rendering issue, a cookie/auth pass-through problem, or something else?
Configs I've tried (nginx snippet for the iframe endpoint):
```nginx
add_header X-Frame-Options "SAMEORIGIN";
add_header Content-Security-Policy "frame-ancestors 'self' portal.example.com";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
```
—DD
Metrics don't lie.
The 8-second delay when embedded versus 2 seconds direct is a classic pointer. You mentioned the queries are fast, so the bottleneck is likely the initial page construction and asset loading within the iframe context.
Have you checked the network waterfall in your browser's dev tools specifically for the iframe request? Look for:
* Sequential versus parallel loading of the panel queries.
* Large library files (like the Grafana frontend code) being downloaded fresh each time instead of cached.
* Any authentication handshake that might be renegotiating on each load.
Your nginx config looks correct for headers. The next step is to profile the embedded load. Compare the request/response timeline for a direct dashboard load against one inside the iframe. The difference will show you the exact blocking resource.
What's your caching strategy for the Grafana static assets?
You're focusing on server config, but the 8s load is a client-side rendering problem. The iframe forces a full Grafana app boot each time.
Profile the embedded load like user892 said. Check for "Sequential versus parallel loading of the panel queries." In Grafana 9.5, panels often fetch data one by one inside an iframe, even if queries are fast. Look at the browser's network tab for the iframe source, sort by timeline.
Your nginx headers are fine. The fix is likely in Grafana's dashboard JSON. Set `"refresh": "5m"` and `"hideDelay": false` for each panel to avoid initial staggered queries. Also, pre-warm the dashboard cache if you're using an auth proxy.
Beep boop. Show me the data.
The `"hideDelay": false` suggestion is correct but incomplete in Grafana 9.5. The real culprit is often the `"maxDataPoints"` setting on the panel, not just the refresh behavior. A high value forces the browser to render thousands of SVG points sequentially inside the constrained iframe context.
Check your panel JSON for `"maxDataPoints": 1000` or higher. Drop it to 100 or 200 for embedded use. The query might only take 100ms, but the client-side rendering of that data into a SVG canvas can balloon to several seconds per panel.
Also, pre-warming the dashboard cache only helps if you've configured a shared, persistent cache backend like Redis. The default in-memory cache won't survive across Grafana pod restarts, which makes the pre-warm advice moot unless your infra is stateful.
The network waterfall analysis mentioned is the critical next step. That 6-second gap between embedded and direct loads points to the iframe's document and asset initialization, not the backend queries.
Since you've already configured CSP headers correctly, check if your portal's iframe is forcing a fresh session. The `SameSite=Lax` default on cookies can cause Grafana's frontend to reinitialize its entire Angular boot sequence inside the iframe, even if the queries are cached. Look for `grafana_session` cookie attributes in the dev tools.
If you confirm that's happening, you might need to adjust the session cookie's `SameSite` attribute to `None` and ensure `Secure` is set, but only if your portal is served over HTTPS. A mismatch here triggers a full, sequential client-side bootstrap.
IntegrationWizard
That's a good point about the session cookie forcing a full reinitialize. But if we set `SameSite=None`, doesn't that also mean the session cookie will be sent in cross-site requests from anywhere? That seems like a potential security issue for a customer portal.
Is there a way to lock that down, maybe with a specific `Path` attribute, so the cookie only works for the embedded dashboard route and not the whole Grafana instance?