Overview
By default, every managed role (signoz-admin, signoz-editor, signoz-viewer) can query all telemetry data in the workspace. In this tutorial you'll create a custom role that can query only the telemetry of a specific service or deployment environment. This is useful when a team owns a few services, or when only some users should see production data.
What you'll do:
- Create a custom role with telemetry transactions scoped to a service or an environment.
- Assign the role so it replaces the user's managed role.
- Validate that queries outside the scope are denied.
Prerequisites
Before you start, make sure you have:
- An active SigNoz license.
- The
signoz-adminrole (role assignment is admin-only). - Telemetry that carries the
service.nameresource attribute, and thedeployment.environment.nameresource attribute if you scope by environment.
Step 1: Create the scoped custom role
- Go to Settings > Roles and click Custom role.
- Enter a name (for example,
checkout-telemetry). - Configure the Transaction Groups below, then click Create role.
Telemetry resources support a single relation, read, and are scoped with telemetry selectors of the form <query_type>/<key>/<value>. Use one of these keys:
| To scope by | Key | Example selector |
|---|---|---|
| Service | resource.service.name | builder_query/resource.service.name/checkout |
| Environment | resource.deployment.environment.name | builder_query/resource.deployment.environment.name/prod |
Interactive mode: Under each telemetry resource (Logs, Traces, Metrics), set the selector to Only selected and use the selector wizard: choose Builder Query as the query type, select resource.service.name or resource.deployment.environment.name in the Key dropdown, and enter the service or environment name as the value. Repeat for each signal the role should access.

JSON mode: Paste the following to scope the role to a service:
[
{
"objectGroup": {
"resource": { "kind": "logs", "type": "telemetryresource" },
"selectors": ["builder_query/resource.service.name/<service-name>"]
},
"relation": "read"
},
{
"objectGroup": {
"resource": { "kind": "traces", "type": "telemetryresource" },
"selectors": ["builder_query/resource.service.name/<service-name>"]
},
"relation": "read"
},
{
"objectGroup": {
"resource": { "kind": "metrics", "type": "telemetryresource" },
"selectors": ["builder_query/resource.service.name/<service-name>"]
},
"relation": "read"
}
]Verify these values:
<service-name>: The value of theservice.nameresource attribute, for examplecheckout.
To scope the role to an environment instead, use the selector builder_query/resource.deployment.environment.name/<environment>, where <environment> is the value of the deployment.environment.name resource attribute, for example prod.
To scope the role to more than one service or environment, add each selector to the selectors array.
Step 2: Assign the role
On Settings > Identity & Access > Members, open the member and assign checkout-telemetry.
Validate
Sign in as a user holding only the scoped role and open the Logs Explorer:
- Run a query with the filter
resource.service.name = '<service-name>'. The query succeeds and returns only that service's data. - Run a query without that filter. The query is rejected with a
403"not authorized" error. - Run a query with the filter
service.name = '<service-name>', without theresource.prefix. The query is also rejected with a403.
How Your Queries Are Checked
The transaction is a gate, not a row filter: queries that pin a scoped key at the top level of their filter with = or IN are admitted, and everything else is rejected with a 403. The key must be written with the resource. prefix in the filter. This applies wherever the query runs (explorers, dashboards, alerts, and the API). For the complete evaluation rules, the allow/deny matrix, and enforcement behavior, see the Telemetry Access Reference.
Troubleshooting
403 on a dashboard panel, saved view, or alert that filters by service
- Likely cause: The filter uses
service.namewithout theresource.prefix, so the query is checked againstbuilder_query/*. - Fix: Change the filter to
resource.service.name = '<service-name>'. If the filter uses a dashboard variable, write it asresource.service.name = $service. - Verify: The panel or view loads without a
403.
403 on a query that filters by deployment.environment
- Likely cause: The filter uses the older
deployment.environmentattribute, which is not a supported selector key. - Fix: Change the filter to
resource.deployment.environment.name = '<environment>'. - Verify: The query returns
200.
Next Steps
- Telemetry Access Reference — Transaction evaluation and query authorization rules
- Transactions Reference — Per-resource transaction tables and selector formats
- Scope Telemetry Access by Ingestion Key — Scope a role to the data sent with an ingestion key
- Roles — Create and manage managed and custom roles