{"id":21066502,"url":"https://github.com/eidam/cf-workers-prometheus-push-gateway","last_synced_at":"2026-04-01T19:19:12.017Z","repository":{"id":92225759,"uuid":"450935576","full_name":"eidam/cf-workers-prometheus-push-gateway","owner":"eidam","description":"A simple Prometheus (aggregated) push gateway allowing stateless/serverless workloads, ephemeral and batch jobs to easily expose their metrics.","archived":false,"fork":false,"pushed_at":"2022-05-18T10:27:38.000Z","size":1472,"stargazers_count":25,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-02-07T15:58:40.870Z","etag":null,"topics":["cloudflare-workers","durable-objects","prometheus","prometheus-metrics","prometheus-push-gateway","push-gateway","workers"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eidam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-22T21:06:23.000Z","updated_at":"2026-01-30T11:02:39.000Z","dependencies_parsed_at":"2023-05-17T10:00:47.225Z","dependency_job_id":null,"html_url":"https://github.com/eidam/cf-workers-prometheus-push-gateway","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eidam/cf-workers-prometheus-push-gateway","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eidam%2Fcf-workers-prometheus-push-gateway","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eidam%2Fcf-workers-prometheus-push-gateway/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eidam%2Fcf-workers-prometheus-push-gateway/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eidam%2Fcf-workers-prometheus-push-gateway/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eidam","download_url":"https://codeload.github.com/eidam/cf-workers-prometheus-push-gateway/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eidam%2Fcf-workers-prometheus-push-gateway/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31036745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T07:48:52.080Z","status":"ssl_error","status_checked_at":"2026-03-27T07:48:19.562Z","response_time":164,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare-workers","durable-objects","prometheus","prometheus-metrics","prometheus-push-gateway","push-gateway","workers"],"created_at":"2024-11-19T17:59:57.776Z","updated_at":"2026-04-01T19:19:11.994Z","avatar_url":"https://github.com/eidam.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Serverless Prometheus (aggregated) Push Gateway\n\nA simple Prometheus _(aggregated)_ push gateway allowing stateless/serverless workloads, ephemeral and batch jobs to easily expose their metrics. Aggregated metrics are exposed via `/metrics` endpoint and optionally pushed to a remote Prometheus instance.\n\nPowered by [Cloudflare Workers](https://workers.cloudflare.com/), [Durable Objects](https://developers.cloudflare.com/workers/learning/using-durable-objects), and [CRON Triggers](https://developers.cloudflare.com/workers/platform/cron-triggers).\n\n![Prometheus metrics](./.github/img/prometheus-metrics.png)\n\n## Features\n\n- **Simple PATCH counter** - no need for a client libraries for a counter metric, just send `PATCH /metrics/:metricName?label1=value1\u0026label2=value2` to increment its value.\n- **Aggregated metrics** - received values are added up to the current (label matching) metrics. All metrics exposed on `GET /metrics`.\n- **Automatic push to a remote prometheus server** - metrics are (optionally) pushed to a `remote_write` prometheus endpoint on each CRON Trigger execution. See [Grafana Cloud](https://grafana.com/products/cloud/features/#cloud-metrics) _(generous free tier)_ for a managed Prometheus with Grafana.\n\n## Deployment\n\nCloudflare Account with Paid Workers is needed.\n\n1. `yarn`\n1. `yarn deploy`\n1. `(optional)` add following secrets _(either via Cloudflare Dashboard or with `npx wrangler@beta secret put`)_\n    - `SECRET_PROM_ENDPOINT` (e.g. `https://prometheus-us-central1.grafana.net/api/prom/push`)\n    - `SECRET_PROM_USER` (e.g. 23333)\n    - `SECRET_PROM_TOKEN` (e.g. xxyy)\n\n## Send metrics\n\nThere are a couple of easy ways to push your metrics, the `POST /metrics` endpoint is compatible with any prometheus client library configured to use it as a push gateway.\n\nIn case Cloudflare Workers are the only clients, its recommended to deploy this Workers with no routes attached to it and use Service bindings.\n\n1. `POST /metrics` - accepts [prometheus text-based format](https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format).\n2. `PATCH /metrics/:metricName?label1=value1\u0026label2=value2` - simplified counter increments that works well with no libraries needed.\n\n### Examples\n\n**curl**\n\n1. Send curl \n    ```\n    curl -x PATCH https://worker.example.com/metrics/metric_name?foo=bar\n    ```\n1. Send `POST` request with body in [prometheus text-based format](https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format)\n    ```bash\n    cat \u003c\u003cEOF | curl --data-binary @- https://worker.example.com/metrics\n    # TYPE some_metric counter\n    some_metric{label=\"val1\"} 42\n    # TYPE another_metric gauge\n    # HELP another_metric Just an example.\n    another_metric 2398.283\n    EOF\n    ```\n\n**Workers**\n\n1. A simple `worker_request` counter that will keep track of request countries. \n    ```js\n    export default {\n        async fetch(request, env, ctx) {\n            ctx.waitUntil(\n                fetch(`https://worker.example.com/metrics/worker_request?country=${request.cf.country}\u0026anotherLabel=value`, {\n                    method: \"PATCH\"\n                })\n            )\n            return new Response(\"Hello World!\")\n        }\n    }\n    ```\n1. [promjs](https://github.com/weaveworks/promjs) _(or any other js library)_\n   ```js\n    import prom from 'promjs';\n    export default {\n        async fetch(request, env, ctx) {\n            const registry = prom()\n            const counter = registry.create('counter', 'my_counter', 'A counter for things')\n            \n            // process tasks, e.g. orders\n            counter.inc({user: \"user1\", plan: \"pro\"})\n            counter.add(3, {user: \"user2\", plan: \"free\"})\n            counter.inc({user: \"user3\", plan: \"pro\"})\n\n            ctx.waitUntil(\n                fetch(`https://worker.example.com/metrics`, {\n                    method: \"POST\",\n                    body: JSON.stringify(registry.metrics())\n                })\n            )\n\n        }\n    }\n   ``` \n\n## Delete metrics\n\n- `DELETE /metrics/__all` to delete all metrics\n- `DELETE /metrics/:metricName` to delete a specific metric,\n- `DELETE /metrics/:metricName?foo=bar` to delete a metric matching specific labels only _(all labels need to match)_\n\n## Limitations\n\n- Max ~100rps, as no Durable Objects sharding is in place. (TODO)\n- `counter` and `gauge` metric types supported only. (`histogram` WIP)\n- No auth. If a public route needed, Cloudflare Access is highly recommended.\n\n## Thank you\n\nInspired by [Prometheus Push Gateway](https://github.com/prometheus/pushgateway) and [Prometheus Aggregation Gateway](https://github.com/weaveworks/prom-aggregation-gateway)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feidam%2Fcf-workers-prometheus-push-gateway","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feidam%2Fcf-workers-prometheus-push-gateway","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feidam%2Fcf-workers-prometheus-push-gateway/lists"}