When a custom Grafana panel plugin is the right build
A custom Grafana panel plugin is a React-based plugin that renders data inside a dashboard, and it is worth building only after the panels Grafana ships and transformations have been tried and have failed to show the data your internal system produces. A team usually reaches this point when an internal system exposes a shape of data, such as a topology, a scheduling grid or a status matrix, that no bundled visualization can draw faithfully even after reshaping the query output. Before any code is written, list the specific display requirement, then test it against the built-in panels, the transformation options and the data source's own query features. Write down which of those fail and why, because that list becomes the scope of the plugin.
The cost of a panel plugin does not end when the first version works. The plugin depends on Grafana's frontend packages and plugin APIs, so each Grafana release that changes those APIs can require code changes, and the plugin must be retested against every minor release your instance runs. Ask any partner or internal team to estimate that recurring maintenance as a separate line item, along with who owns the upgrade calendar. Confirm the Grafana version range you will target and how long your organization expects each version to remain in service, using the supported release cadence in the Grafana upgrade guidance as your reference point.
The rest of this page walks through the decision in order: how a panel plugin is structured, how its options and field configuration are defined, how to test it with plugin-e2e, and how to compare the finished panel against the existing options. If the comparison favors a built-in panel after all, the work is still useful, because the requirements and the transformation chain you documented can be reused. If the custom panel wins, you will know which controls, field settings and test cases it must carry before the build starts.
What a Grafana panel plugin does
A Grafana panel plugin is a frontend component that draws one visualization on a dashboard. Its parts are a metadata file, a component that renders data, an options editor and field config defaults. Each part answers a different question, so decide what the custom panel must do before choosing which parts to build.
Plugin metadata in plugin.json
The plugin.json file identifies the plugin to Grafana. It declares a plugin ID, the plugin type as a panel, the display name, author and version, and the Grafana versions the plugin depends on. Grafana reads this file at startup to decide whether to load the plugin, so a wrong type or an ID that clashes with another plugin can stop the panel from appearing at all. Check the dependency range against every Grafana version in your environment before you publish.
The panel component
The panel component is the React code Grafana renders inside the dashboard panel frame. Grafana passes it the query results as data frames, the options saved for this panel, the field config and the panel's current width and height. The component should only transform and draw that input. If it fetches data directly from an internal API instead, it can skip the time range and template variables the dashboard has already resolved, along with the permission checks that come with them.
The options editor
The options editor is the form that appears in the panel editor and writes values into the panel's options object. You define it in the plugin module by registering option inputs such as text, switch, select and number fields, each with a default. Keep options for things that change how the panel draws, such as labels or a color scheme, and leave data shaping to queries or transformations. Every option you add is saved in each dashboard that uses the panel, so renaming or removing one later needs a migration plan.
Field config defaults
Field config holds per-field settings such as units, decimals, thresholds, value mappings and colors. Users can set these standard options in the panel editor, so a well-built panel gets the same controls that other panels offer. Confirm in the plugin documentation which standard options your Grafana version exposes, then set defaults that suit your data. A panel that ignores field config still renders, but users lose the unit and threshold controls they expect.
The module entry point
The module entry point is the file Grafana loads at runtime, declared in plugin.json and built into the distribution folder. It exports the panel plugin object that connects the component, the options editor and the field config setup. Check that the build output includes the compiled module, the plugin.json file and the static assets together. A missing file usually appears as a panel that fails to load on the dashboard, so test the built package in a running Grafana instance, not only in the development server.
Matching the Grafana version
Panel interfaces can change between Grafana releases, so the plugin must be tested against each version it claims to support. Grafana publishes its releases on GitHub, and recent minor versions include 13.1.0 and 13.2.0 with frequent patch releases. Before you start, confirm the current plugin API in the Grafana plugin documentation for your target version. Record which Grafana version the plugin was built and tested on, so the next upgrade has a clear baseline.
Panel, transformation or data source: choosing the build path
Most dashboard requirements are met by the panels Grafana ships with, configured through field overrides. Overrides let you set units, thresholds, value mappings, colors, data links and display names per field or per series without writing any code. This is the lowest-cost path because the configuration lives in the dashboard JSON, travels with provisioned dashboards and is upgraded with Grafana itself.
- Good fit: charts that differ only in units, thresholds, colors or labels from data you already query.
- Cannot do: draw a visual that the shipped panel types do not support, or apply logic that depends on a custom rendering library.
- Maintenance cost: low, but override sprawl across many dashboards becomes hard to review unless you standardize it through provisioned templates.
- Check: confirm the panel types available in your Grafana version before assuming a gap exists.
Before leaving this option, list the specific visual your users need and check whether an override or a different built-in panel type already renders it.
Transformations reshape query results inside the dashboard before a panel renders them. They can join frames, filter rows, rename or organize fields, compute reductions and pivot data. Use them when the data is available from a data source but its shape does not match the panel you want. Because transformations run in the browser on each dashboard load, they cost panel rendering time and are harder to reuse than a query change.
- Good fit: combining two queries, reshaping a table, or calculating a derived column for an existing panel.
- Cannot do: change how a panel draws its output, or work around a data source that cannot return the rows you need.
- Maintenance cost: moderate; chains of transformations are easy to break when a query label changes and are hard to test outside the dashboard.
- Check: measure load time on large time ranges, since heavy transformation chains affect every viewer.
If the same transformation chain appears on many dashboards, consider moving it into the query or data source layer before considering a plugin.
Grafana's plugin catalog includes panels and data sources published by Grafana Labs and the community. Installing an existing plugin is the next option to test when built-in panels do not meet a need. Plugins are installed on the server, so they add an update and review obligation, and some require a license or a Grafana Cloud plan. Confirm each plugin's license, signature status and compatibility with your Grafana version before you adopt it for production.
- Good fit: a common visual that the community has already built and maintains, such as a specialized chart type.
- Cannot do: render data from your internal systems in a way the plugin author did not design, or meet internal review rules without an approval step.
- Maintenance cost: recurring; you track plugin releases, test them against each Grafana upgrade and retire plugins that stop being maintained.
- Check: ask whether the plugin is signed and whether its maintainer still publishes compatible releases.
Before approving a third-party plugin for a regulated environment, document its source, license and update path in the same review as your internal plugins.
A custom panel plugin is the right choice when the rendering itself is the requirement and none of the options above can produce it. Examples include a process diagram bound to live values, a domain-specific chart type or a control panel for an internal system. Building one means owning a React and TypeScript codebase, the plugin manifest, its options editor and its tests, and keeping it working across Grafana releases. Plan the build and the upkeep together, and treat the plugin as a product that your team owns.
- Good fit: a visual that depends on a specific data shape, interaction or drawing logic that the built-in panels and standard plugins cannot provide.
- Cannot do: replace a query fix or a dashboard layout change; if the data is wrong, a panel will not correct it.
- Maintenance cost: the highest of the four options, with recurring work for dependency updates, Grafana version compatibility, security review and signing for private use.
- Check: write down the specific rendering requirement and confirm the other three options cannot meet it before scoping the build.
Illustrative example: a team that needs a network topology view with live status colors may find that no built-in panel draws edges between nodes, which is the case where a custom panel is justified.
How a panel plugin moves from scaffold to a dashboard
The sequence turns a visualization idea into a signed panel plugin that has passed tests on staging before it reaches production dashboards. Each step hands over a named artifact, so the owner can see what exists before the next step starts.
Scope the visualization and its data frame shape
The panel owner and the dashboard authors agree on the question the panel answers, the data sources it reads, and the shape of the data frames it will receive. Someone from the platform team checks which existing panels and transformations could already produce the view, so the custom build is justified against them. The step is done when the team has a short written spec listing the input fields, expected units, empty and error states, and the options authors will need to set. Confirm early whether the panel must work in dashboards viewed by other teams, because that affects permissions and rollout.
Scaffold the plugin with create-plugin
A developer runs Grafana's create-plugin scaffolding tool to generate a panel plugin project with the standard directory layout, build configuration and plugin metadata. They set the plugin ID, name and author details, and confirm the generated project builds and loads in a local Grafana instance. The developer should use a plugin ID that follows the organization's naming convention, because the ID becomes part of the signed package and cannot be changed later without re-signing. The step is done when a placeholder panel renders on a local dashboard and the project is under version control.
Define options and field config
The developer declares the panel's options, the settings authors see in the panel editor, and any field config defaults that Grafana's standard field settings should not override. Options cover things like display mode, thresholds or labels, while field config covers units, decimals and color behavior that users already know from other panels. The output is a typed options definition and a short editor walkthrough that the spec owner reviews to confirm authors can configure every item in the spec without reading source code. Keep options to what the spec requires, since every added option becomes a compatibility obligation for later versions.
Build the rendering logic
The developer writes the component that reads the incoming data frames, applies the field config, and draws the visualization, handling resizing, empty data, missing fields and error states. Transformation logic should stay small and tested, because the panel should display what the query and transformations provide rather than reshape data in ways authors cannot see. The step is done when the panel renders the spec's sample data correctly in a local dashboard, at several panel sizes, with light and dark themes, and when each empty or error state shows a message the dashboard author can act on.
Write plugin-e2e tests
The developer adds end-to-end tests with the plugin-e2e framework, which drives a real Grafana instance and checks that the panel loads, that editor options change the rendered output, and that the empty and error states behave as specified. Tests should run against the Grafana version the organization actually uses, and the team should record which versions they cover. The output is a test suite that runs in the continuous integration pipeline and a short list of the scenarios it covers. Ask the developer to confirm which Grafana versions the suite runs against before the staging step begins.
Sign and package for private use
The team builds the production bundle, signs it for private use, and packages it as the artifact that instances will load. Signing ties the plugin to the Grafana instances it may run on, so the root URLs in the signature must match each target instance, and any change to those URLs requires re-signing. The output is a versioned, signed plugin archive stored in the organization's artifact repository, along with the record of the root URLs and the access policy token owner. The step is done when a test instance loads the signed archive without enabling unsigned plugins.
Roll out to a staging instance first
The signed plugin is installed on a staging Grafana instance that matches production in version, data sources and authentication settings. Dashboard authors test the panel against real queries and permissions, and the owner checks that the plugin loads for users in each team that will see it. The step is done when the spec's acceptance checklist passes on staging and the team has recorded the Grafana version, plugin version and any issues found. Rollout to production should wait for that record, and the same signed archive should be the one promoted, not a rebuilt copy.
Promote to production and hand over
Once staging sign-off is recorded, the same signed plugin version is installed on production, and the team confirms it loads on each instance with the expected root URLs. The developer hands over the source repository, test suite, options reference, signing procedure and upgrade notes to the team that will maintain it. The handover is complete when the maintainers can rebuild, test, sign and deploy a new version without the original developer. Plan a review of the plugin at each Grafana upgrade, since panel APIs can change between releases.
How options and field config shape the panel
Panel options and field config are the two places where a custom panel receives settings, and they belong to different people. Panel options are defined by the plugin author and set by the dashboard author for that one panel, such as whether a gauge shows a legend or which orientation a chart uses. Field config is different: Grafana applies it to each field in the data frame, so the same settings (units, decimals, min and max, thresholds, value mappings and overrides) can change how every series or column is drawn. Overrides let a dashboard author target specific fields by name or type and set field config for only those fields. Before writing code, decide which settings are panel-specific and which should reuse Grafana's standard field config so that dashboard authors already know how to use them. A panel that ignores thresholds or units, for example, will surprise users who expect the same behavior as built-in panels.
Options are declared in the plugin code, typically in the module file that registers the panel, where the builder defines each option's name, type, default value and editor. Each option you add is a value your rendering code must handle for every combination of other options, data shapes and empty states. That is why keeping options few reduces the testing surface: every extra option multiplies the cases that need automated checks in plugin-e2e and manual review in the dashboard editor. Start with the smallest set that serves the internal use case, and add an option only when a dashboard author has a concrete need that field config or a transformation cannot meet. Record the reason for each option so later maintainers can judge whether it still earns its place.
The option builder, field config keys and editor components change between Grafana versions, so do not copy them from older examples or blog posts. Confirm the exact API names, registration calls and field config support against the plugin documentation for the Grafana version you target, and note the version in your repository so that upgrades are reviewed deliberately. Test the panel against your target Grafana release in a non-production instance before rollout, and check how thresholds and overrides behave with your real data shapes, including null values and very large series counts. If the panel is meant to be used across several instances, confirm that the same options and field config produce the same results on each one.
What drives the effort and cost of a custom panel
This table lists the factors that change how much work a custom Grafana panel takes to build, test, sign and keep working. Read each row for what raises or lowers effort and what to request in a written quote. The main takeaway is that the number of options and the data frame contract usually matter more than the chart itself.
| Driver | Effect on effort | What to ask for in a quote |
|---|---|---|
| Number of panel options | Each option adds editor UI, defaults, validation and migration logic. Options that change rendering or data processing add more testing than cosmetic ones. | A list of every option with its type, default and whether it affects rendering, data handling or both. |
| Data frame contract | Accepting one known shape of data is simple. Accepting several shapes, multiple queries, or fields tagged by type and role requires detection code and more test cases. | The data frame shapes the panel must accept, how it reacts to missing or mismatched fields, and the sample data used for testing. |
| Rendering library choice | Using React and existing Grafana UI components keeps the panel aligned with Grafana's look and upgrade path. A third-party charting library adds its own bundle size, licensing review and version pinning. | The rendering library, its license, the version to be pinned, and who maintains the upgrade when it changes. |
| Dashboard feature interaction | Supporting template variables, the time range, drilldown links, annotations or panel-level interactions means reading dashboard state and reacting to changes, which is where most edge cases appear. | A list of dashboard features the panel must honor, with the expected behavior for each and the dashboards used for acceptance. |
| Test coverage with plugin-e2e | Option defaults, rendering states and dashboard interactions each need browser tests. Coverage grows with every option and interaction, and tests must be kept current as the UI changes. | The test cases to be delivered, the Grafana versions they run against, and whether the test suite is handed over with the code. |
| Signing and distribution | Signing and deploying to one instance is a small step. Several instances, separate environments or air-gapped networks add signing configuration, per-instance URL matching and a repeatable release process. | The number of instances, the signing approach for each, and the release steps the client team will own afterward. |
| Upkeep across Grafana releases | Grafana ships major releases yearly and minor releases every other month, and each minor release is supported for 9 months (per the Grafana upgrade guidance). Panels that use internal Grafana APIs need more regression work at each upgrade. | A named upgrade plan covering the Grafana versions in use, who runs regression tests, and the support window the quote covers. |
How to test a panel plugin with plugin-e2e
What is plugin-e2e and why use it for a Grafana panel?
plugin-e2e is Grafana's end-to-end testing toolkit for plugins, built on Playwright, that drives a real Grafana instance and checks the plugin as a user would see it. Unit tests can confirm your option logic, but they cannot show that the panel renders inside a dashboard, reads data frames correctly and survives a page reload. For a panel plugin, the end-to-end layer is where rendering, option changes and field config effects are verified against the actual Grafana UI. Confirm the plugin-e2e version that matches your Grafana release and your plugin's @grafana/create-plugin scaffold before you write the first test, because the test API changes between versions.
How do test fixtures set up dashboards and panels for a panel plugin?
Fixtures give each test a known starting state: a Grafana instance with your plugin loaded, a dashboard containing your panel, and a data source that returns predictable frames. The usual pattern is to provision a test dashboard JSON that places the panel with specific options and field config, then have the test open that dashboard and interact with it. Keep fixture data small and deterministic, such as a testdata data source scenario or a static frame set, so assertions do not depend on live systems. Store fixture dashboards in the plugin repository next to the tests so they are versioned with the code they exercise.
What should a panel plugin end-to-end test assert?
Assert the behaviors a user relies on, not the internal markup of your component. The core checks are:
- The panel mounts and draws its visualization without console errors.
- Changing an option in the panel editor updates the rendered output.
- Field config settings such as units, thresholds, color mode and value mappings change how values appear.
- Empty data shows the message you designed, and a query error shows an error state instead of a blank panel.
- Time range or refresh changes re-render the panel with new frames.
Each assertion should map to a requirement in your plugin's options and field config specification, so a failing test points to a concrete regression.
How do I test empty and error states in a Grafana panel?
Create dedicated fixture scenarios for each state: a query that returns zero rows, one that returns frames without the fields your panel expects, and one that returns an error from the data source. Then assert the visible result for each, such as a no-data message, a validation notice or the panel's error indicator. These cases are where custom panels most often fail silently, because code that assumes a numeric time field can crash on an empty frame. Testing them explicitly also protects against Grafana changes to how frames and errors are delivered to panels.
How often do plugin-e2e tests break when Grafana is upgraded?
The frequency depends on how much your tests rely on Grafana's UI selectors and on the plugin-e2e API, and it cannot be estimated in advance. Grafana ships minor releases every other month and patch releases at least monthly, according to its upgrade guidance, so a test suite needs a scheduled run against each supported Grafana version rather than a one-time check. Treat the suite as maintained code: pin the Grafana image used in CI, run the suite against the next minor release in a staging environment, and budget time for selector and API updates. Check the Grafana upgrade documentation for the support window of each minor release you target.
Can my own team write and maintain plugin-e2e tests, or do I need a partner?
Most teams with a frontend developer and a working knowledge of Playwright can write the first suite for a single panel. The effort grows with the number of options, field config behaviors, supported Grafana versions and the CI infrastructure needed to run a real Grafana instance on each change. What a partner typically adds is a scoped test plan, fixture design across several panels, CI pipelines that run against multiple Grafana versions and handover documentation. DeployOpen plans, builds and documents this work in client infrastructure under a written scope, and ongoing test upkeep can be covered by a retainer.
What inputs should I prepare before asking for a quote on plugin test work?
Prepare the list of panel options and field config settings, the Grafana versions you must support, the data sources or fixture types you need, and where your CI runs. Also state whether tests must run against air-gapped or restricted networks, since a real Grafana instance must be reachable from the test runner. A written scope listing these items lets a provider quote fixed deliverables, such as a named set of test scenarios and a CI job, rather than an open-ended testing effort. DeployOpen does not publish prices, and a quote follows from that written scope.
How a custom panel connects to the rest of the stack
A custom panel does not work alone. It renders frames from a data source, sits on dashboards placed through provisioning, must be signed before a private instance will load it, and needs a pipeline that rebuilds and tests it on every change. Each connection has a different owner, so settle who maintains each one before the build starts.
Data source plugins that supply frames
The panel only renders what the query layer returns. Decide whether the data comes from a built-in data source, a Grafana Labs plugin or an internal data source plugin, and confirm the field names, types and time fields the panel expects. Transformations can reshape frames before the panel sees them, so check which transformations your dashboards already rely on. If the panel depends on a custom data source, its release cycle must match the panel's, because a change to one can break the other. Ownership usually sits with the team that runs the data source.
Dashboards and provisioning that place the panel
A panel becomes useful when a dashboard references its plugin ID and options. Provisioning lets dashboards and data sources load from YAML or JSON files at startup, so the panel's placement and default options can be versioned with the rest of the instance. Confirm that the plugin ID in each dashboard JSON matches the one in the plugin's plugin.json, and that options saved by a newer version still load in older dashboards. The platform team typically owns the provisioning files, and the panel author owns the option schema.
Plugin signing for private distribution
Grafana loads unsigned plugins only when an administrator allows them, so a private panel needs a signature for normal instances. Signing ties the plugin to the URLs of the instances that will run it, and a change to those URLs means signing again. Your team needs an access policy token with the right scope and must decide whether one signature covers every instance or each environment gets its own. Confirm this process with your security team before the first release, since it affects who can publish.
CI pipeline that builds and tests
Each change should trigger a build of the frontend bundle, the unit tests, and the end-to-end tests run with plugin-e2e against a Grafana version you choose. Pin the Grafana version in the pipeline so a test run does not pass on a version your instances do not run. The pipeline should also produce the signed artifact or hand it to a signing step, and store the build so a rollback is a known file. The engineering team owns the pipeline, and the platform team should review how the artifact reaches each instance.
Grafana versions the panel must track
Plugin APIs change between Grafana releases, so the panel needs a planned support window. Grafana supports each minor release for 9 months and the last minor release of a major version for 15 months, according to its upgrade guidance. Build a test matrix that covers the Grafana version in production and the next one, and schedule updates against the release calendar. Ask who approves a version bump and who tests dashboards after an instance upgrade.
Keeping a custom panel working across Grafana releases
A custom panel is only as durable as its fit with the Grafana release running in production. Grafana ships major releases once a year, in April or May, minor releases every other month and patch releases at least monthly. Each minor release is supported for 9 months, and the last minor release of a major version for 15 months, according to the Grafana upgrade guidance. Your panel will therefore see several Grafana versions in its working life, and the team should plan for that cadence rather than treat each upgrade as an exception.
Every upgrade touches three things, and each needs its own retest. The first is the Grafana host: the panel's options pane, field config defaults, and rendering in the dashboard grid, along with any dependency on Grafana's shared UI components that changed in the release notes. The second is the build toolchain, meaning the Node.js version, the bundler and the @grafana/create-plugin tooling that produce the plugin bundle and its plugin.json metadata. The third is the dependency set in package.json, including the @grafana/* packages and test libraries. Run the plugin-e2e suite against the new Grafana version, check the build output, and confirm that the panel still loads in a staging instance before the production change.
Schedule these checks in a fixed upgrade window instead of reacting to each patch. A monthly window fits the patch cadence, and a quarterly review of the panel's dependency pins keeps the toolchain from falling behind the supported Grafana versions. Ask the partner or internal owner to document the tested Grafana versions, the owner of each dependency update, and the rollback steps for the plugin bundle. Confirm the minimum Grafana version your panel declares in its plugin metadata and check it against the version range your instances will run during the planned upgrade.
Questions teams ask before building a Grafana panel plugin
When is a custom Grafana panel needed instead of transformations?
A custom panel is needed when the visual form itself is the requirement, such as a specialized chart type, a status layout or an interaction that no built-in panel offers, and transformations cannot reshape the data into it. Transformations, field overrides and existing panels handle most reshaping, aggregation and labeling work, and they keep the logic inside dashboards that your team can already edit. Before scoping a plugin, list each display requirement and test whether a built-in panel with transformations meets it. Each requirement that fails that test is a candidate for a panel plugin, and that list becomes the basis of the scope.
What drives the cost of a custom Grafana panel plugin?
Cost follows the number of display requirements, the complexity of the options and field config editor, the number of data shapes the panel must accept, and how much testing and documentation the handover includes. Fixed-scope engagements price the written scope, so the clearer the requirements, the more predictable the quote. Ask for the cost split between discovery, build, plugin-e2e tests, packaging and handover training, and whether each item is one-time or recurring. Ongoing Grafana version upgrades are a separate, recurring item, and a retainer is one way to cover them.
How long does building a custom Grafana panel plugin take?
Duration depends on how many panel features the scope includes, how well the data contract is defined, and how many Grafana instances the plugin must support. The largest delays usually come from unclear data shapes, late changes to options, and waiting for test data from source systems. Ask the provider to show the build sequence, the milestones that need your sign-off, and which tasks depend on your team. No duration figure is given here because timing varies by scope and your environment, so confirm it against a written plan.
What must our team provide before a panel plugin build starts?
Your team needs to provide a data frame contract that describes each field name, type, unit and expected cardinality, along with representative test data that covers normal values, empty results, nulls and error responses. You also need the Grafana versions and editions in use, a target list of instances, the access model for dashboards, and a named owner who can approve options and display decisions. Without a fixed contract and realistic data, panel tests will check the wrong behavior and changes will return late in the project.
Can our own engineers build a Grafana panel plugin?
Yes, if they have front-end development skills in TypeScript and React and can work with the Grafana plugin tooling and the plugin-e2e test framework. The main effort is learning the plugin structure, options and field config APIs, and the release conventions for each Grafana version. Teams without that experience usually take longer and need a review step before release. Assess your team's skills against the scope, and decide whether to build in-house, hire a partner for the initial build, or combine both with a handover plan.
Who maintains a custom panel plugin after handover?
The owner of the plugin maintains it, and that role must be named before handover. Maintenance covers upgrades for each Grafana minor and major release, fixes for breaking changes, updates to tests, dependency updates and signing for private distribution. Grafana publishes upgrade guidance with minor releases every other month, patch releases at least monthly and major releases once a year, so the maintenance workload recurs. Ask whether the scope includes a retainer for ongoing upgrades or whether your team will carry that work.
Does a custom panel plugin change how we license or distribute Grafana?
Plugins use their own licenses, and Grafana Labs states that plugins, SDKs and agent software kept licenses other than AGPLv3 when Grafana, Loki and Tempo were relicensed on April 20, 2021. Your plugin's license is a decision for your legal team and should be recorded in the scope. Confirm how the plugin will be distributed to your instances, because private use requires signing, and confirm the terms that apply to any third-party libraries the panel depends on.
How DeployOpen scopes and delivers a panel plugin
A custom panel plugin touches code, tests, signing and the people who will maintain it after handover. DeployOpen agrees the boundaries of that work in writing before anything is built, so the deliverables, exclusions and acceptance checks are known to both sides.
Written fixed scope first
Most engagements are fixed-scope, so the panel's purpose, the data it reads, the Grafana versions it must support and the browsers and instances it runs on are agreed in writing before work starts. Ask for the scope to name which panel options are in, which field config behavior is excluded, and how changes after kickoff are priced. A scope that says only "build a panel" leaves the acceptance question open until the end of the project.
Plugin code and options
Deliverables include the panel source: plugin metadata, the panel component, its options editor and any field config defaults it needs. Confirm who owns the repository, which license applies to the code, and whether the build uses the current Grafana plugin tooling. Ask for a short walkthrough of how each option maps to a rendered behavior so your team can change it later.
Automated tests with plugin-e2e
Tests are part of the delivery, not an extra. The expected set covers end-to-end checks of the panel in a running Grafana, against the Grafana versions you name in scope. Ask which scenarios are covered, such as option changes, empty data and the no-data state, and where the test suite runs in your CI system.
Signing and distribution
Private panels need a signing step before Grafana will load them without relaxing plugin trust settings. The deliverable should state which signing token and root URLs are used, who holds the credentials, and how the plugin is re-signed when an instance URL changes. Ask for the signing process to be documented so your release engineers can repeat it without the vendor.
Handover documentation
Handover includes build and release instructions, the supported Grafana version range, known limitations and a runbook for upgrades. Ask for a short record of the design decisions, such as why the panel uses a transformation or a backend call, so future maintainers know what to keep. Confirm the format and where the documents live before work starts.
Optional retainers and quotes
DeployOpen does not publish a price list. A quote follows from the written scope, and the cost depends on the panel's complexity, test coverage and signing setup. Optional retainers cover upgrades when new Grafana releases arrive and continuous testing of the panel. Ask for the quote to separate one-time build work from any recurring retainer.

