Why Grafana 13 Moved Image Renderer into a Separate Service

R. B. Atai10 min read

The architectural reasons behind Grafana 13 removing Image Renderer plugin mode—and the security, scaling, and operational trade-offs of a separate service.

Grafana 13 has removed support for running Image Renderer as a plugin. The renderer itself still exists, but only as a separate service. On the surface, this looks like an inconvenient migration: what used to be installed as a plugin now requires another component.

The more interesting question is why a feature that looks like part of Grafana should no longer live alongside the core application.

Grafana Labs has not published a single statement saying, “We removed the plugin for this one reason.” But the direction is clear from the renderer’s history, its complete rewrite in version 5, and the problems described by the team itself. Rendering is not an ordinary Grafana extension. It means running a full Chromium instance over dashboard data and UI. That process has a different risk profile, resource pattern, and update cycle. A separate service makes the difference explicit.

Why the plugin used to make sense

Plugin mode had one major advantage: a simple mental model. An administrator installed an extension and gained panel images for alerts, exports, and reports. There was no separate network path to design, no additional deployment to watch, and no need to explain why an Export button required its own service.

That simplicity matters for a feature used only a few times a day. The plugin lowered the adoption barrier and hid the internal machinery. Under a light workload, the renderer felt almost like a library: Grafana asked for an image, got one back, and the user never had to think about the browser underneath.

But the convenient packaging created the impression that Grafana and Chromium were the same kind of system. They are not.

Core Grafana stores dashboards, manages users, executes queries, and coordinates plugins. The renderer starts a browser, loads a page, executes JavaScript, waits for data, and captures a visual result. The first system needs to stay continuously available and predictable. The second is inherently heavy, bursty, and built on the vast attack surface of a modern browser.

Plugin mode made installation easier while obscuring an important architectural boundary.

Reason one: Chromium is a poor neighbor for the core application

The renderer needs headless Chromium because a modern dashboard cannot be faithfully converted into an image with a simple HTML template. It has to reproduce almost the same client runtime that a user sees: JavaScript, fonts, canvas, plugins, network requests, and dynamic layout.

Accuracy has a cost. A browser consumes memory in bursts, creates child processes, and depends on data-source response times. One complex dashboard can cost far more than dozens of ordinary Grafana requests. When several rendering jobs arrive together, the renderer starts competing with the UI and API that Grafana exists to provide.

Moving it into a separate service does not make rendering cheaper. It makes the cost independently manageable:

  • concurrent browsers can be limited without throttling Grafana;
  • the renderer can receive dedicated resources or dedicated nodes;
  • it can scale on a rendering queue instead of UI traffic;
  • an overloaded renderer can be stopped or restarted without disturbing core Grafana.

This separation matters more than any individual setting. A heavy secondary function no longer has to share the fate of the observability system itself.

Reason two: a browser changes the security model

In 2025, Grafana Labs issued urgent Image Renderer fixes for critical Chromium vulnerabilities. In a separate case, a Grafana vulnerability could use an installed renderer for full-read SSRF. This does not mean plugin mode was always unsafe or that service mode is automatically secure. It demonstrates the potential impact: a browser next to Grafana is an active execution environment that can reach the network and process complex, untrusted content.

For Image Renderer 5, the team rewrote the service in Go and strengthened Chromium isolation for Grafana Cloud. The official description covers a restrictive Linux namespace sandbox: processes cannot leave persistent files behind and are terminated after the job. That promise should not be transferred automatically to every self-managed installation. Grafana Cloud’s security wrapper and an ordinary separate container are not the same thing.

The service boundary nevertheless creates a place where security can be designed deliberately. The renderer can live in its own network segment, be restricted to a narrow set of destinations, run with minimal privileges, and remain short-lived. In plugin mode, the same behavior looked like an implementation detail of Grafana even though it launched a browser with access to its environment.

The architectural point is not “turn everything into microservices.” It is containment: if the browser fails or is compromised, the blast radius should be smaller.

Reason three: Grafana and the renderer have different update cycles

Grafana is updated as an observability platform. Chromium is updated as a browser, and urgent memory and sandbox fixes can arrive independently of Grafana. When the renderer is packaged as a plugin, users can easily tie its lifecycle to the Grafana version: the core application was upgraded, so everything around it must be current too.

A separate service breaks that convenient but mistaken link. A browser-bearing component has to move at its own pace. Grafana Labs now supports only the latest version of the Image Renderer service and recommends pinning a production image rather than relying on a floating latest tag.

For a self-managed operator, this creates more work. For Grafana’s developers, it creates room to evolve the renderer as an independent product: rewrite its runtime, change page-readiness heuristics, add memory-aware rate limiting, and test its interaction with several supported Grafana versions.

It is an honest trade: less hidden coupling inside the product, more visible responsibility for the operator.

What the architecture gains

The first benefit is failure isolation. Memory exhaustion or a stuck browser does not have to take Grafana down with it. The renderer can be constrained and restarted independently.

The second is independent scaling. Grafana’s API and a batch of one hundred PDFs need different resources. A single scaling policy is rarely right for both.

The third is a separate security policy. The browser can be allowed to reach only the network destinations it actually needs instead of inheriting broad access to Grafana’s environment.

The fourth is visible cost. When the renderer is hidden inside an installation, PDF generation feels almost free. A separate service reveals how much CPU, memory, and engineering attention an automated report really consumes.

The fifth is reuse. One renderer pool can potentially serve several Grafana instances if the team is prepared to design workload and trust separation. That can be more rational than keeping a browser beside every instance.

There is also a product benefit for Grafana Labs. A single service architecture is closer to how the renderer operates in Grafana Cloud: the component can be improved, secured, and scaled separately from Grafana core. This is not a stated official reason for removing the plugin, but it is a logical consequence of the boundary Grafana chose.

What gets worse

The main drawback is that a simple feature becomes a distributed system. Grafana and the renderer now depend on networking, authentication, and separate availability. The user still clicks one button, but the owner of the installation is responsible for more moving parts.

The second drawback is that the operational cost shifts to the OSS user. Grafana Cloud hides the renderer as managed infrastructure. A self-managed team gains another service to update, observe, and secure. The capability still exists, but its full cost is now harder to ignore.

The third is a new failure point. A separate renderer protects Grafana from browser load, but the renderer itself can become unavailable. Dashboards continue to work while alert images or PDFs stop. That is a good degradation mode for the platform, but still an incident for the reporting process.

The fourth is that isolation is not automatic. Running the renderer in the same pod, with broad network access and no limits, changes the arrow on an architecture diagram without materially changing the risk. Service mode provides the means to separate responsibilities; it does not perform that work for the operator.

The fifth is more friction for local development and small installations. For a team with one Grafana instance and a few renders per week, the old plugin may have been the more economical design. Grafana’s decision optimizes long-term platform security and operations, not the minimum container count for every user.

This is not merely decomposition—it clarifies Grafana’s role

The change can be read as a separation between a control plane and an execution plane.

Grafana decides what should be shown: which dashboard, time range, variables, and access rights apply. The renderer performs the expensive work of deciding how to reproduce that page in a browser and produce a static result.

When both roles are hidden inside one installation unit, export appears to be a natural extension of viewing a dashboard. But an interactive screen and a reproducible report have different requirements. A person can wait for a panel to finish, notice an error, and refresh the page. An automated report has to decide when a dashboard is ready, what counts as failure, and whether a partial result should be sent.

The renderer is therefore not simply “Grafana without a monitor.” It is a separate executor with its own load, readiness, and failure policies. Grafana 13 makes that reality part of the product architecture.

A separate renderer still does not create a reporting system

There is an easy but incorrect conclusion to draw: if the renderer is now a service, running it beside Grafana OSS must provide scheduled reports. It does not.

The renderer turns dashboard state into an image or material for a PDF. A reporting system also decides when to start a job, who receives the result, how failures are retried, how long files are stored, and what happens when a panel loads only partially.

Grafana Enterprise combines these layers into its scheduled reports feature. In OSS, the renderer remains a building block. The team must build and operate the rest of the pipeline or hand it to a specialized service. The options are discussed in more detail in “Grafana OSS scheduled reports: PDF and email options”.

Who benefits from running their own renderer

Service mode suits organizations that value control over simplicity. If Grafana sits inside a closed environment, data must remain on the organization’s infrastructure, and the team already knows how to operate browser workloads, a separate renderer creates a clear control point. Its cost can be accepted as part of the platform.

For a small team producing only a few reports each month, the conclusion may be the opposite. Maintaining a service that sits idle most of the time just to generate PDFs is questionable economics—especially when the business request is “email this dashboard to management once a week,” not “build a reliable browser rendering farm.”

The choice is not between a correct and an incorrect architecture. It is between different forms of control:

  • a self-managed renderer keeps data, updates, and resilience inside the team;
  • Grafana Cloud or Enterprise turns the same pipeline into a managed product feature;
  • a separate reporting service removes renderer operations but requires careful scrutiny of which data and credentials it receives.

DashPDF uses a customer-controlled push model: an app plugin inside Grafana collects dashboard JSON and data frames and sends a snapshot through an outbound request. The service does not connect to the customer’s Grafana or receive data-source credentials. The intent is to keep access control on the customer side without requiring the customer to operate Chromium. This model has compatibility boundaries of its own and does not replace the native renderer in every scenario.

What actually changed in Grafana 13

The plugin removal can fit into one line of release notes, but its meaning is broader. Grafana stopped treating browser rendering as a lightweight extension of the core application.

The benefits are systemic: a smaller shared blast radius, independent scaling, a separate security update cycle, and an honest view of rendering cost. The drawbacks are systemic too: more components, more responsibility for self-managed teams, and a higher barrier for small installations.

This is a sensible architecture for a platform that has to serve both individual OSS installations and Grafana Cloud. It is not necessarily more convenient for every user. That is the central trade-off in Grafana 13: a cleaner responsibility boundary won over simpler installation.

Conclusion

Grafana moved Image Renderer to where it belongs architecturally: outside the core application boundary. Chromium is too heavy, too independently updated, and too security-sensitive to keep disguising it as an ordinary plugin.

For Grafana owners, this is not a free improvement. Isolation is purchased with additional infrastructure. After Grafana 13, the important question is not “Which configuration should we write?” but “Do we want to own a rendering system at all?” If the answer is yes, a separate service provides a more honest and manageable architecture. If not, it is worth choosing a solution that delivers the report rather than another component to operate.

Sources

  1. Grafana Labs — Upgrade to Grafana v13.0. https://grafana.com/docs/grafana/latest/upgrade-guide/upgrade-v13.0/
  2. Grafana Labs — Grafana Image Renderer plugin support removed. https://grafana.com/whats-new/2026-04-14-grafana-image-renderer-plugin-support-removed/
  3. Grafana Labs — What's new in the Grafana Image Renderer: higher-quality results, security enhancements, and more. https://grafana.com/blog/whats-new-in-the-grafana-image-renderer-higher-quality-results-security-enhancements-and-more/
  4. Grafana Labs — Critical severity security release for Grafana Image Renderer. https://grafana.com/blog/grafana-security-update-critical-severity-security-release-for-cve-2025-5959-cve-2025-6554-cve-2025-6191-and-cve-2025-6192-in-grafana-image-renderer-plugin-and-synthetic-monitoring-agent/
  5. Grafana Labs — High severity security fix for CVE-2025-4123. https://grafana.com/blog/grafana-security-release-high-severity-security-fix-for-cve-2025-4123/
  6. Grafana Labs — Set up image rendering. https://grafana.com/docs/grafana/latest/setup-grafana/image-rendering/
  7. Grafana Labs — Create and manage reports. https://grafana.com/docs/grafana/latest/visualizations/dashboards/create-reports/

Share this article

Why Grafana 13 Moved Image Renderer to a Separate Service | DashPDF