Monitor multiple databases
As your infrastructure grows beyond a single database, you need to monitor multiple database instances. This guide covers deployment patterns, configuration strategies, and labeling best practices for managing multiple databases with Database Observability.
Before you begin
Complete setup for at least one database:
You also need:
- Grafana Alloy running and connected to Grafana Cloud
- Grafana Cloud remote write credentials for Prometheus and Loki
Choose a deployment pattern
Choose a deployment pattern based on your infrastructure and scale requirements.
Single Alloy instance
One Alloy instance monitors all databases.
┌─────────────────┐
│ Grafana Alloy │
│ ┌─────────┐ │ ┌──────────┐
│ │ MySQL 1 │──┼────▶│ mysql-1 │
│ ├─────────┤ │ └──────────┘
│ │ MySQL 2 │──┼────▶│ mysql-2 │
│ ├─────────┤ │ └──────────┘
│ │ PG 1 │──┼────▶│ postgres │
│ └─────────┘ │ └──────────┘
└────────┬────────┘
│
▼
Grafana CloudAdvantages:
- Simple to deploy and manage
- Single configuration file
- Lower resource overhead
Disadvantages:
- Single point of failure
- Network latency to remote databases
- Scaling limits
Best for:
- Small to medium deployments (< 20 databases)
- Databases in same network/region
- Development and staging environments
Distributed Alloy instances
Deploy Alloy alongside each database or group of databases.
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Region A │ │ Region B │ │ Region C │
│ ┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │
│ │ Alloy │ │ │ │ Alloy │ │ │ │ Alloy │ │
│ │ ↓ │ │ │ │ ↓ │ │ │ │ ↓ │ │
│ │ MySQL │ │ │ │ PG │ │ │ │ MySQL │ │
│ └────────┘ │ │ └────────┘ │ │ └────────┘ │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │
└─────────────────┼─────────────────┘
▼
Grafana CloudAdvantages:
- High availability (one Alloy failure doesn’t affect others)
- Low latency to local databases
- Scales horizontally
- Aligns with infrastructure boundaries
Disadvantages:
- More instances to manage
- Distributed configuration
- Higher total resource usage
Best for:
- Large deployments (20+ databases)
- Multi-region infrastructure
- Production environments requiring high availability
Configure multiple databases
Single Alloy with multiple databases
Add a component block for each database:
// ====================
// Database 1: MySQL orders
// ====================
local.file "mysql_orders_secret" {
filename = "/var/lib/alloy/mysql_orders_dsn"
is_secret = true
}
prometheus.exporter.mysql "orders" {
data_source_name = local.file.mysql_orders_secret.content
enable_collectors = ["perf_schema.eventsstatements"]
}
database_observability.mysql "orders" {
data_source_name = local.file.mysql_orders_secret.content
forward_to = [loki.relabel.orders.receiver]
targets = prometheus.exporter.mysql.orders.targets
}
loki.relabel "orders" {
forward_to = [loki.write.default.receiver]
rule {
target_label = "instance"
replacement = "orders.db.example.com:3306"
}
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "app"
replacement = "order-service"
}
}
discovery.relabel "orders" {
targets = database_observability.mysql.orders.targets
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "instance"
replacement = "orders.db.example.com:3306"
}
rule {
target_label = "app"
replacement = "order-service"
}
}
prometheus.scrape "orders" {
targets = discovery.relabel.orders.output
forward_to = [prometheus.remote_write.default.receiver]
}
// ====================
// Database 2: PostgreSQL users
// ====================
local.file "pg_users_secret" {
filename = "/var/lib/alloy/pg_users_dsn"
is_secret = true
}
prometheus.exporter.postgres "users" {
data_source_names = [local.file.pg_users_secret.content]
enabled_collectors = ["stat_statements"]
autodiscovery {
enabled = true
}
}
database_observability.postgres "users" {
data_source_name = local.file.pg_users_secret.content
forward_to = [loki.relabel.users.receiver]
targets = prometheus.exporter.postgres.users.targets
}
loki.relabel "users" {
forward_to = [loki.write.default.receiver]
rule {
target_label = "instance"
replacement = "users.db.example.com:5432"
}
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "app"
replacement = "user-service"
}
}
discovery.relabel "users" {
targets = database_observability.postgres.users.targets
rule {
target_label = "job"
replacement = "integrations/db-o11y"
}
rule {
target_label = "instance"
replacement = "users.db.example.com:5432"
}
rule {
target_label = "app"
replacement = "user-service"
}
}
prometheus.scrape "users" {
targets = discovery.relabel.users.output
forward_to = [prometheus.remote_write.default.receiver]
}
// ====================
// Shared outputs
// ====================
prometheus.remote_write "default" {
endpoint {
url = "https://prometheus-prod-01-us-east-0.grafana.net/api/prom/push"
basic_auth {
username = sys.env("GRAFANA_CLOUD_PROMETHEUS_USERNAME")
password = sys.env("GRAFANA_CLOUD_API_KEY")
}
}
}
loki.write "default" {
endpoint {
url = "https://logs-prod-us-east-0.grafana.net/loki/api/v1/push"
basic_auth {
username = sys.env("GRAFANA_CLOUD_LOKI_USERNAME")
password = sys.env("GRAFANA_CLOUD_API_KEY")
}
}
}Mixed database types
You can monitor both MySQL and PostgreSQL from the same Alloy instance:
// MySQL databases
database_observability.mysql "mysql_1" { /* ... */ }
database_observability.mysql "mysql_2" { /* ... */ }
// PostgreSQL databases
database_observability.postgres "pg_1" { /* ... */ }
database_observability.postgres "pg_2" { /* ... */ }Each component is independent and can have different configurations.
Choose a labeling strategy
Consistent labels help you filter and organize databases in Database Observability dashboards.
Required labels
These labels must be set correctly for Database Observability to function:
Recommended labels
Add these labels to organize and filter databases:
Label consistency
Labels must match between loki.relabel and discovery.relabel:
// Logs labels
loki.relabel "mydb" {
rule {
target_label = "instance"
replacement = "mydb.example.com:3306"
}
rule {
target_label = "environment"
replacement = "production"
}
}
// Metrics labels - must match!
discovery.relabel "mydb" {
rule {
target_label = "instance"
replacement = "mydb.example.com:3306" // Same value
}
rule {
target_label = "environment"
replacement = "production" // Same value
}
}For complete label guidance including best practices, environment variables, and troubleshooting, refer to the Labels reference.
Add cloud provider integrations
Add a cloud_provider block in Grafana Alloy to correlate database telemetry with infrastructure metrics from AWS CloudWatch, Azure Monitor, or Google Cloud Monitoring.
The block also enables the Cloud Provider Observability integration in Database Observability.
Configure Alloy using the platform setup guides:
- AWS RDS MySQL, AWS Aurora MySQL, AWS RDS PostgreSQL, AWS Aurora PostgreSQL
- Azure Database for MySQL, Azure Database for PostgreSQL
- Google Cloud SQL MySQL, Google Cloud SQL PostgreSQL
The following examples show the cloud_provider block for each platform.
AWS RDS / Aurora
database_observability.mysql "rds" {
data_source_name = local.file.rds_secret.content
forward_to = [loki.relabel.rds.receiver]
targets = prometheus.exporter.mysql.rds.targets
cloud_provider {
aws {
arn = "arn:aws:rds:us-east-1:123456789012:db:mydb"
}
}
}Azure Database
database_observability.postgres "azure" {
data_source_name = local.file.azure_secret.content
forward_to = [loki.relabel.azure.receiver]
targets = prometheus.exporter.postgres.azure.targets
cloud_provider {
azure {
subscription_id = "your-subscription-id"
resource_group = "your-resource-group"
server_name = "your-server-name"
}
}
}Google Cloud SQL
database_observability.mysql "cloudsql" {
data_source_name = local.file.cloudsql_secret.content
forward_to = [loki.relabel.cloudsql.receiver]
targets = prometheus.exporter.mysql.cloudsql.targets
cloud_provider {
gcp {
connection_name = "my-project:us-central1:my-db"
}
}
}The connection_name value is the Cloud SQL instance connection name in project:region:instance format.
You can find it in the Google Cloud console on the instance details page.
The cloud_provider block also enables integration with Cloud Provider Observability.
For navigation between query performance and cloud infrastructure metrics, refer to Access Database Observability in the Cloud Provider Observability documentation for your platform:
- Preconfigured dashboards and alerts
- Preconfigured dashboards and alerts for Azure metrics
- Google Cloud Platform observability
Troubleshoot multi-database setups
When databases don’t appear or data doesn’t correlate correctly, start with these multi-database-specific checks:
- Verify that every database has a unique
instancelabel. - Confirm the
instancevalue matches exactly between theloki.relabelanddiscovery.relabelblocks for the same database. - Check that
jobis exactlyintegrations/db-o11yon every component.
For detailed troubleshooting steps, refer to the dedicated guides:
Related documentation
- Tune Alloy collection: Optimize per-database settings
- Labels reference: Complete label documentation
- Verify telemetry status: Validate configuration health per database


