Subchapter 81.5
references/kubernetes.mdMarkdown8 KBView on GitHub
AI agents: this is one page from PostHog’s docs. Full index of Markdown docs for LLMs: https://posthog.com/llms.txt (opens in a new tab)
Note: Metrics is in open alpha. Any team can turn it on — open Metrics (opens in a new tab) and select Enable metrics in the onboarding view. Setup details, including the ingestion endpoint, may change before general availability.
If your Kubernetes workloads already expose Prometheus-format /metrics endpoints, the PostHog metrics agent scrapes them and forwards everything to PostHog. One helm install, no application changes.
The agent runs as a single instance by default. To scale beyond one pod, use shards rather than replicas: two plain replicas would scrape every target twice and double-count all metrics.
1
Required
You need:
helm v3 installedprometheus.io/scrape: "true" annotation pattern)The chart creates a ClusterRole and ClusterRoleBinding so the agent can discover pods across all namespaces. If your cluster uses strict RBAC policies, confirm you have permission to create cluster-scoped roles.
2
Required
You’ll need your PostHog project token to authenticate metrics requests. This is the same token you use for capturing events with the PostHog SDK.
Important: Use your project token, which starts with
phc_. Do not use a personal API key (which starts withphx_).
You can find your project token in Project Settings (opens in a new tab).
3
Required
Terminal
helm install posthog-metrics-agent oci://ghcr.io/posthog/charts/posthog-metrics-agent \
--set posthog.apiKey=<ph_project_token>For EU Cloud, set the host explicitly:
Terminal
helm install posthog-metrics-agent oci://ghcr.io/posthog/charts/posthog-metrics-agent \
4
Required
By default, the agent discovers and scrapes any pod annotated with prometheus.io/scrape: "true". Two optional annotations control the scrape target:
| Annotation | Default | Description |
|---|---|---|
prometheus.io/scrape | – | Set to "true" to opt a pod in |
prometheus.io/path | /metrics | Override the metrics path |
prometheus.io/port | Pod’s container port | Override the scrape port |
Example pod annotation:
YAML
5
Recommended
Terminal
kubectl get pods -l app.kubernetes.io/name=posthog-metrics-agentIf nothing shows up, check the agent logs for connection or authentication errors:
Terminal
kubectl logs -l app.kubernetes.io/name=posthog-metrics-agent6
Optional
By default, if PostHog is briefly unreachable the agent retries from memory, and a pod restart during that window drops whatever was buffered. To keep those samples, back the queue with a persistent volume:
Terminal
--set persistence.enabled=trueThe chart provisions a volume per agent (using persistence.size and persistence.storageClass), and samples scraped during an outage survive restarts and deliver when PostHog is reachable again.
7
Optional
One agent scrapes every target itself, which is enough for most clusters. For a large target set, run a fleet:
Terminal
--set shards=4The chart switches to a StatefulSet, each pod works out its own shard from its name, and every target is scraped by exactly one pod: nothing is scraped twice, nothing is missed. Combine with persistence.enabled=true to give each shard its own durable queue.
Checkpoint
What you can do with your metrics
| Action | Description |
|---|---|
| Why you need metrics (opens in a new tab) | What metrics show you that events and logs don’t |
| Getting started guide (opens in a new tab) | Pick the right metric type, add attributes carefully, and chart what matters |
| Group and filter | Group by an attribute for one line per value, or filter with key=value chips |
| How metrics works |
| Value | Default | Description |
|---|---|---|
posthog.apiKey | '' | Project token (phc_...). Stored in a chart-managed Secret |
posthog.existingSecret | '' | Name of an existing Secret with a posthog-api-key key. Takes precedence over apiKey |
posthog.host | https://us.i.posthog.com | PostHog ingestion origin. Set to https://eu.i.posthog.com for EU Cloud |
scrape.interval | 15s | How often to scrape targets |
scrape.annotationDiscovery | true | Discover pods via prometheus.io/scrape annotations |
scrape.staticTargets | [] | Fixed host:port targets, e.g. ['my-svc:9090'] |
scrape.extraScrapeConfigs | '' | Raw Prometheus scrape_configs YAML appended verbatim |
shards | 1 | Agent fleet size. Above 1, a StatefulSet partitions targets so each is scraped once |
persistence.enabled | false | Buffer undelivered batches on a persistent volume so restarts lose nothing |
persistence.size | 10Gi | Size of each agent’s queue volume |
persistence.storageClass | '' | StorageClass for the queue volume. Empty uses the cluster default |
podEnv | {} | Extra environment variables for the agent container |
resources.requests.cpu | 100m | CPU request |
resources.requests.memory | 256Mi | Memory request |
resources.limits.memory | 512Mi | Memory limit |
rbac.create | true | Create a ClusterRole for pod discovery |
serviceAccount.create | true | Create a dedicated ServiceAccount |
serviceAccount.name | '' | Override the ServiceAccount name. Required when serviceAccount.create is false |
nodeSelector | {} | Kubernetes node selector |
tolerations | [] | Kubernetes tolerations |
affinity | {} | Kubernetes affinity rules |
Ask PostHog AI
HelpfulCould be better
If you manage secrets separately, point the chart at an existing Kubernetes Secret containing a posthog-api-key key instead of passing the token directly:
Terminal
helm install posthog-metrics-agent oci://ghcr.io/posthog/charts/posthog-metrics-agent \
--set posthog.existingSecret=my-posthog-secretThe API key is stored in a Secret and injected as an environment variable – it never appears in the ConfigMap.
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/custom/metrics"For services that don’t carry Prometheus annotations, add fixed host:port targets:
Terminal
helm install posthog-metrics-agent oci://ghcr.io/posthog/charts/posthog-metrics-agent \
--set posthog.apiKey=<ph_project_token> \
--set 'scrape.staticTargets={my-service:9090,another-service:8080}'You can combine annotation discovery with static targets. To disable annotation discovery entirely and only use static targets, set scrape.annotationDiscovery=false.
For advanced use cases, pass raw Prometheus scrape_configs YAML via scrape.extraScrapeConfigs. This is appended verbatim to the collector configuration.
The agent also exposes its own metrics (scrape successes, queue depth, points sent or dropped) on port 8888, so you can monitor the monitor.
| How metrics are ingested, stored, and queried |
| Query with SQL | Every metric lands in the posthog.metrics table, queryable from the SQL tab |