{"id":26647438,"url":"https://github.com/ar-io/ar-io-node","last_synced_at":"2026-06-06T03:04:26.359Z","repository":{"id":187084818,"uuid":"480614136","full_name":"ar-io/ar-io-node","owner":"ar-io","description":"A scalable and modular gateway built for the permaweb atop the Arweave permanent data storage network.","archived":false,"fork":false,"pushed_at":"2025-04-03T19:16:05.000Z","size":4395,"stargazers_count":105,"open_issues_count":15,"forks_count":71,"subscribers_count":10,"default_branch":"develop","last_synced_at":"2025-04-03T20:26:08.505Z","etag":null,"topics":["arweave","graphql","nodejs","permaweb","protocol","sqlite","typescript","web3"],"latest_commit_sha":null,"homepage":"https://ar.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ar-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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-04-12T01:42:50.000Z","updated_at":"2025-04-03T19:16:09.000Z","dependencies_parsed_at":"2023-10-13T14:06:57.304Z","dependency_job_id":"5c39b722-af4f-4a23-ab89-1fb1410866b2","html_url":"https://github.com/ar-io/ar-io-node","commit_stats":null,"previous_names":["ar-io/ar-io-node"],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-io%2Far-io-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-io%2Far-io-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-io%2Far-io-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ar-io%2Far-io-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ar-io","download_url":"https://codeload.github.com/ar-io/ar-io-node/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247980837,"owners_count":21027808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["arweave","graphql","nodejs","permaweb","protocol","sqlite","typescript","web3"],"created_at":"2025-03-24T23:52:10.078Z","updated_at":"2026-02-12T00:20:29.546Z","avatar_url":"https://github.com/ar-io.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AR.IO Gateway Node\n\n[![codecov](https://codecov.io/gh/ar-io/ar-io-node/graph/badge.svg?token=F3BJ7W74HY)](https://codecov.io/gh/ar-io/ar-io-node)\n[![protocol.land](https://arweave.net/eZp8gOeR8Yl_cyH9jJToaCrt2He1PHr0pR4o-mHbEcY)](https://protocol.land/#/repository/713c1b6f-86c8-493e-b2e6-6cb231862b93)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ar-io/ar-io-node)\n\n## Getting Started\n\n- [Linux Installation Instructions](./docs/linux-setup.md)\n- [Windows Installation Instructions](./docs/windows-setup.md)\n\n## Dev Workflow\n\n### Install dependencies\n\n`yarn install`\n\n### Initialize the SQLite DB\n\n`yarn db:migrate up`\n\n### Run lint\n\n`yarn lint:check`\n\n### Run tests\n\n`yarn test`\n\n### Run the service\n\nWith defaults:\n\n`yarn start`\n\nStarting at an arbitrary block (only works immediately after initial DB\nmigration):\n\n`START_HEIGHT=800000 yarn start`\n\n## Dev Docs\n\n### Schema (WIP)\n\n- [Bundle schema]\n\n## Docker\n\n### Standalone AR.IO Node\n\nYou can run the ar.io gateway as a standalone docker container:\n\n```shell\ndocker build . -t ar-io-core:latest\ndocker run -p 4000:4000 -v ar-io-data:/app/data ar-io-core:latest\n```\n\nTo run with a specified start height (sets height on first run only):\n\n```shell\ndocker run -e START_HEIGHT=800000 -v $PWD/data/:/app/data ar-io-core:latest\n```\n\n### Envoy \u0026 AR.IO Node\n\nYou can also run [Envoy] alongside an `ar.io` node via [Docker Compose]. Envoy\nwill proxy routes to `arweave.net` not yet implemented in the ar.io node.\n\n```shell\ndocker compose up --build\n```\n\nOnce running, requests can be directed to Envoy server at `localhost:3000`.\n\n### Run a Turbo Bundler as a Sidecar\n\nYou can run a [Turbo] [ANS-104] data item bundler as a sidecar to the ar.io gateway service. This will allow the deployed system to accept data items and bundle them into a single transaction before submitting them to the network. The bundler's APIs will be reachable at the `/bundler/` path. For more information on its APIs, you can access docs at `/bundler/api-docs/`.\n\nNote: A local bundler configured to integrate with an ar.io node relies upon GraphQL indexing of recently bundled and uploaded data to manage its pipeline operations. The ar.io node should have its indexes synced up to Arweave's current block height minus 18 blocks before starting up the bundler's services stack.\n\nBundling services are most easily managed via an independent docker compose file whose services share their network with that of the core services docker compose stack. This allows you to spin the services up when your core service is prepared to integrate with it, or down whenever you want without affecting your core services stack.\n\nTo get started, supply the required environment variables in an environment variables file (e.g. `.env.bundler`) for the integration, most notably:\n\n- `BUNDLER_ARWEAVE_WALLET`: a stringified JWK wallet used for uploading bundles to Arweave.\n- `ALLOW_LISTED_ADDRESSES`: a comma-separated list of allowed uploader wallet addresses (normalized). See [Managing Bundler Access](#managing-bundler-access) for more permissioning options.\n\nSee the `.env.bundler.example` file for other important configuration options, including settings for serving bundler-uploaded data items instantly from your gateway.\n\nOnce environment variables are set, run docker compose with the bundler-specific compose file.\n\n```shell\ndocker compose --env-file ./.env.bundler --file docker-compose.bundler.yaml up\n```\n\nNow, the bundler service will be running alongside the ar.io gateway. Your gateway will now accept data items at `\u003cyour gateway url\u003e/bundler/tx` 🚀\n\n#### Managing Bundler Access\n\nBy default, the bundler will only accept data items uploaded by data item signers whose normalized wallet addresses are in the `ALLOW_LISTED_ADDRESSES` list. But the following other permissioning configuration schemes are possible:\n\n| Scheme                 | ALLOW_LISTED_ADDRESSES                      | SKIP_BALANCE_CHECKS | ALLOW_LISTED_SIGNATURE_TYPES | PAYMENT_SERVICE_BASE_URL |\n| ---------------------- | ------------------------------------------- | ------------------- | ---------------------------- | ------------------------ |\n| Allow specific wallets | comma-separated normalized wallet addresses | false               | EMPTY or supplied            | EMPTY                    |\n| Allow specific chains  | EMPTY or supplied                           | false               | arbundles sigtype int        | EMPTY                    |\n| Allow all              | n/a                                         | true                | n/a                          | n/a                      |\n| Allow none             | EMPTY                                       | false               | EMPTY                        | EMPTY                    |\n| Allow payers           | EMPTY or supplied                           | false               | EMPTY or supplied            | your payment svc url     |\n\n### Run an AO Compute Unit (CU) as a Sidecar\n\nAO Compute Units are useful for interacting with AO Processes in manner that avoids Process side effects and that does not require gas payment via \"[Dry Runs]\".\n\nAO CU's rely on bundlers to periodically upload checkpoint data for evaluated Process memory. Additionally, they rely on gateway GQL to find those checkpoints, Scheduler assignments for each Process, and more. The indexing workload to support arbitrary AO Processes is effectively the indexing workload for most of Arweave's recent history. However, most recent AO Testnet Processes's data was bundled by Turbo in dedicated bundles with the tag:\n\n```\nBundler-App-Name: AO\n```\n\nIncluding that tag filter in your indexing filters and indexing data from block height 1378000 forward should include the vast majority of the needed testnet data.\n\nIf you control your own SU and can easily identify its L1 data transactions' tags, you can simply filter on those from a block height that captures all of the SU data for your processes of interest.\n\nSimilarly to the bundler sidecar, the CU service is most easily managed via an independent docker compose file whose services share their network with that of the core services docker compose stack.\n\nTo get started, supply the required environment variables in an environment variables file (e.g. `.env.ao`) for the integration, most notably:\n\n- `CU_WALLET`: a stringified JWK wallet used for uploading CU checkpoints to Arweave.\n- `PROCESS_CHECKPOINT_TRUSTED_OWNERS`: a comma-separated list of CU checkpoint uploader wallet addresses(normalized).\n\nSee the `.env.ao.example` or the environment overrides in `docker-compose.ao.yaml` file for other important configuration options.\n\nOnce environment variables are set, run docker compose with the ao-specific compose file.\n\n```shell\ndocker compose --env-file ./.env.ao --file docker-compose.ao.yaml up\n```\n\nNow, the CU service will be running alongside the ar.io gateway. Within the docker network it can be reached at `http://envoy:3000/ao/cu` and `http://ao-cu:6363`. From the docker host machine, it can be reached at `http://localhost:3000/ao/cu` and `http://localhost:6363`. From your custom domain configured to forward traffic to envoy, it can be reached at `\u003cyour gateway url\u003e/ao/cu`.\n\n## Configuration\n\nWhen running via `docker compose`, it will read a `.env` file in the project root\ndirectory and use the environment variables set there.\n\n### GraphQL Pass-Through\n\nAdd the following to your `.env` file to proxy GraphQL to another server while\nusing the ar.io gateway to serve data (using arweave.net GraphQL as an example):\n\n```\nGRAPHQL_HOST=arweave.net\nGRAPHQL_PORT=443\n```\n\n### Unbundling\nThe ar.io gateway supports unbundling and indexing [ANS-104] bundle data. To\nenable this add the following environment variables to your `.env` file:\n\n```\nANS104_UNBUNDLE_FILTER=\"\u003cfilter string\u003e\"\nANS104_INDEX_FILTER=\"\u003cfilter string\u003e\"\n```\n\n`ANS104_UNBUNDLE_FILTER` determines which TXs and data items (in the case of\nnested bundles) are unbundled, and `ANS104_INDEX_FILTER` determines which data\nitems within a bundle get indexed.\n\nThe following types of filters are supported:\n\n```\n{ \"never\": true } # the default\n{ \"always\": true }\n{ \"attributes\": { \"owner_address\": \u003cowner address\u003e, ... }}\n{ \"tags\": [{ \"name\": \u003cutf8 tag name\u003e, \"value\": \u003cutf8 tag value\u003e }, { \"name\": \u003cutf8 tag name\u003e }, ...]}\n{ \"and\": [ \u003cnested filter\u003e, ... ]}\n{ \"or\": [ \u003cnested filter\u003e, ... ]}\n{ \"not\": [ \u003cnested filter\u003e, ... ]}\n\n```\n\nPlace an ANS-104 bundle at the start of the queue for unbundling and indexing\non your gateway:\n\n```\ncurl -X PUT -H \"Authorization: Bearer \u003cADMIN_KEY\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  \"http://\u003cHOST\u003e:\u003cPORT\u003e/ar-io/admin/queue-tx\" \\\n  -d '{ \"id\": \"\u003cID\u003e\" }'\n\n```\n\nNote: ANS-104 indexing support is currently experimental. It has been tested\nsuccessfully with small sets of bundles (using filters), but you may still\nencounter problems with it when indexing larger sets of transactions.\n\nFor detailed information about filter types, operators, and advanced examples, see [Filter Documentation](docs/filters.md).\n\n### Root Transaction Index (CDB64)\n\nThe gateway ships with a pre-built CDB64 index that provides O(1) lookups to\nresolve data item IDs to their containing L1 Arweave transactions. It is enabled\nby default and covers ~964 million non-AO, non-Redstone data items up to block\nheight 1,820,000.\n\nTo disable it, remove `cdb` from `ROOT_TX_LOOKUP_ORDER`. To use custom index\nsources, set `CDB64_ROOT_TX_INDEX_SOURCES`. See [docs/envs.md](docs/envs.md)\nfor all CDB64 configuration options and [docs/cdb64-guide.md](docs/cdb64-guide.md)\nfor operational guidance.\n\n### Webhook Emission\n\nThe ar.io gateway includes a feature to emit webhooks to specified servers when a transaction or data item is indexed and matches a predefined filter. This feature allows for real-time notifications and integrations based on the transaction and data indexing.\n\nTo use this feature, you need to set up two environment variables in your `.env` file:\n\n1. **WEBHOOK_TARGET_SERVERS**: This is a comma-separated list of servers where the webhooks will be sent.\n\n   Format: `WEBHOOK_TARGET_SERVERS=\"\u003cserver1\u003e,\u003cserver2\u003e,...\"`\n\n2. **WEBHOOK_INDEX_FILTER**: This filter determines which transactions or data items will trigger the webhook emission.\n\n3. **WEBHOOK_BLOCK_FILTER**: This filter determines which blocks will trigger the webhook emission.\n\nThe filter syntax is identical to `ANS104_INDEX_FILTER`. Supported filter types include:\n\n- `{ \"never\": true }` (default)\n- `{ \"always\": true }`\n- `{ \"attributes\": { \"owner\": \u003cowner key\u003e, ... }}`\n- `{ \"tags\": [{ \"name\": \u003cutf8 tag name\u003e, \"value\": \u003cutf8 tag value\u003e }, { \"name\": \u003cutf8 tag name\u003e }, ...]}`\n- `{ \"and\": [ \u003cnested filter\u003e, ... ]}`\n- `{ \"or\": [ \u003cnested filter\u003e, ... ]}`\n\nExample: `WEBHOOK_INDEX_FILTER=\"{ \"tags\": [{ \"name\": \"App-Name\", \"value\": \"MyApp\" }, { \"name\": \"IPFS-Add\" }]}\"`\n\nAfter setting up the environment variables, the ar.io gateway will monitor for transactions or data items that match the `WEBHOOK_INDEX_FILTER`. Once a match is found, a webhook will be emitted to all the servers listed in `WEBHOOK_TARGET_SERVERS`.\n\nEnsure that the target servers are configured to receive and process these webhooks appropriately.\n\nFor detailed information about filter types, operators, and advanced examples, see [Filter Documentation](docs/filters.md).\n\n### ArNS\n\nAdd the following to your `.env` file to enable ArNS resolution:\n\n```\nARNS_ROOT_HOST=\u003cgateway-hostname\u003e\n```\n\nFor example if your gateway's hostname was `my-gateway.net` your `.env` would\ncontain the following:\n\n```\nARNS_ROOT_HOST=my-gateway.net\n```\n\nThis would allow you to resolve names like `my-arns-name.my-gateway.net` provided\nyou correctly configured a wildcard DNS entry for your gateway.\n\nNote: ArNS data ID resolution is currently delegated to `arweave.dev`. Routing is\nhandled locally, but ArNS state is not yet computed locally. Local ArNS state\ncomputation will be added in a future release. Also, be aware, ArNS is still using\na test contract. Resolved names should be considered temporary.\n\n### Wallet association\n\nIn order to participate in the [ar.io network](https://ar.io/), gateways need\nto associate themselves with a wallet. This can be configured by setting the\n`AR_IO_WALLET` environment variable. Once set, the associated wallet address is\nvisible via the `/ar-io/info` endpoint.\n\nSimilarly, network participants must make observations of other gateways and\nsubmit them. The wallet for this is configured using the `OBSERVER_WALLET`\nenvironment variable. An associated key file is also required to upload\nobservation reports. The key file must be placed in\n`./wallets/\u003cOBSERVER_WALLET\u003e.json` (`\u003cOBSERVER_WALLET\u003e` should be replaced with\nthe address of the wallet you are using).\n\n### Admin API key\n\nHTTP endpoints under '/ar-io/admin' are protected by an admin API key. On startup,\nthe admin key is read from the `ADMIN_API_KEY` environment variable. If no key is\nset, a random key is generated and logged. To make a request to an admin endpoint\nadd an `Authorization: Bearer \u003cADMIN_API_KEY\u003e` header to your request.\n\n### Content Moderation\n\nBlock a specific TX/data item ID on your gateway:\n\n```\ncurl -X PUT -H \"Authorization: Bearer \u003cADMIN_KEY\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  \"http://\u003cHOST\u003e:\u003cPORT\u003e/ar-io/admin/block-data\" \\\n  -d '{ \"id\": \"\u003cID\u003e\", \"notes\": \"Example notes\", \"source\": \"Example source\" }'\n\n```\n\n`notes` and `source` are for documentation only. `source` is intended to be an\nidentifier of a particular source of IDs to block (e.g. the name of a\nblocklist). `notes` is a text field that can be used to further describe why a\nparticular ID is blocked.\n\n### Monitoring and Observability\n\nThe ar-io-node leverages [Prometheus] to collect metrics from the system and\nrecommends [Grafana] to visualize them. To access a templated Grafana dashboard\nfor the ar.io gateway, you can run:\n\n```\ndocker compose --file docker-compose.grafana.yaml up -d\n```\n\nOnce the dashboard is running, you can access it at\n`http://localhost:1024/grafana` and login with the username and password\n`admin`.\n\nThis dashboard is pre-configured to work with the ar.io gateway metrics exposed\nvia the `ar-io-core` service and is ready to be used without any additional\nconfiguration for simple observability. You can modify the dashboard to better\nfit your needs by editing the `dashboard.json` file. Refer to the [Grafana\ndocumentation] to learn more about how to create and modify Grafana dashboards\nusing JSON model files.\n\n#### OpenTelemetry and Distributed Tracing\n\nThe ar-io-node uses [OpenTelemetry] for distributed tracing, providing deep visibility into request flows and performance bottlenecks. When deployed with docker-compose, traces are automatically routed through an **OTEL Collector sidecar** that implements intelligent **tail-based sampling** to reduce telemetry costs by 80-95% while maintaining complete visibility into errors and performance issues.\n\n**How Tail Sampling Works:**\n\nUnlike traditional head-based sampling (which decides whether to keep a trace at the start), tail sampling waits until the entire trace completes before making a decision. This enables five intelligent sampling policies:\n\n1. **100% Error Capture**: All traces with errors (5xx responses, exceptions) are captured\n2. **100% Slow Request Capture**: All requests exceeding 2 seconds (configurable) are captured\n3. **100% Payment Capture**: All traces with verified x402 payments are captured for billing and compliance\n4. **100% Paid Token Capture**: All traces that consumed paid rate limit tokens are captured\n5. **Probabilistic Baseline**: 1% (configurable) of successful, fast, unpaid requests for baseline metrics\n\nThis approach ensures you never miss critical failures, paid traffic, or compliance-relevant requests while dramatically reducing storage and analysis costs for free-tier traffic.\n\n**Configuration:**\n\nTo use OTEL Collector with tail sampling in docker-compose:\n\n1. Set your telemetry destination and API key (configure ONE based on your backend):\n   ```bash\n   # Honeycomb\n   OTEL_COLLECTOR_DESTINATION_ENDPOINT=https://api.honeycomb.io\n   OTEL_COLLECTOR_HONEYCOMB_API_KEY=your-honeycomb-api-key\n\n   # OR Grafana Cloud Tempo\n   OTEL_COLLECTOR_DESTINATION_ENDPOINT=https://otlp-gateway-prod-us-central-0.grafana.net/otlp\n   OTEL_COLLECTOR_GRAFANA_CLOUD_API_KEY=your-base64-encoded-key\n\n   # OR Datadog\n   OTEL_COLLECTOR_DESTINATION_ENDPOINT=https://trace.agent.datadoghq.com\n   OTEL_COLLECTOR_DATADOG_API_KEY=your-datadog-api-key\n\n   # OR New Relic\n   OTEL_COLLECTOR_DESTINATION_ENDPOINT=https://otlp.nr-data.net\n   OTEL_COLLECTOR_NEW_RELIC_API_KEY=your-new-relic-license-key\n\n   # OR Elastic APM\n   OTEL_COLLECTOR_DESTINATION_ENDPOINT=https://your-deployment.apm.region.cloud.es.io\n   OTEL_COLLECTOR_ELASTIC_API_KEY=your-elastic-secret-token\n   ```\n\n2. Optionally adjust sampling parameters:\n   ```bash\n   # Sample 5% of successful requests instead of 1%\n   OTEL_TAIL_SAMPLING_SUCCESS_RATE=5\n\n   # Capture requests slower than 1 second instead of 2\n   OTEL_TAIL_SAMPLING_SLOW_THRESHOLD_MS=1000\n   ```\n\n3. Start the stack:\n   ```bash\n   docker compose up -d\n   ```\n\nThe collector runs automatically as part of the docker-compose stack. Traces flow through: `ar-io-node` → `otel-collector` → `your telemetry backend`.\n\n**Non-Docker Deployments:**\n\nFor non-docker deployments, you can send traces directly to your telemetry backend by setting:\n```bash\nOTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io\nOTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=your-api-key\n```\n\nNote: Direct export bypasses tail sampling and uses head-based sampling via `OTEL_TRACING_SAMPLING_RATE_DENOMINATOR`.\n\n**Supported Telemetry Backends:**\n\nThe OTEL Collector works with any OTLP-compatible backend:\n- Honeycomb\n- Grafana Cloud (Tempo)\n- Datadog\n- New Relic\n- Elastic APM\n- Self-hosted: Jaeger, Zipkin, Tempo\n\nFor complete configuration options, see the [environment variables documentation](docs/envs.md).\n\n[OpenTelemetry]: https://opentelemetry.io/\n\n### Log Filtering\n\nThe AR.IO Node supports filtering Winston logs with the `LOG_FILTER`\nenvironment variable (or `CORE_LOG_FILTER` when using docker-compose). This\nhelps reduce log noise by showing only logs that match specific criteria.\n\nFilter logs using the same JSON-based filtering syntax used for bundle filters,\nwith the filter logic applying to log attributes instead of bundle attributes:\n\n```\n# Only show logs from ArNS resolvers\nLOG_FILTER={\"attributes\":{\"class\":\"CompositeArNSResolver\"}}\n\n# Only show logs from the on-demand ArNS resolver\nLOG_FILTER={\"attributes\":{\"class\":\"OnDemandArNSResolver\"}}\n\n# Show logs from multiple ArNS components using logical operators\nLOG_FILTER={\"or\":[{\"attributes\":{\"class\":\"CompositeArNSResolver\"}},{\"attributes\":{\"class\":\"OnDemandArNSResolver\"}}]}\n```\n\nFor more details on filter syntax, see the [filter\ndocumentation](docs/filters.md) - while this documentation focuses on bundle\nfilters, the filter structure and logic apply to log filtering as well.\n\n## Principles and Practices\n\n### Architecture\n\n- Code to interfaces.\n- Separate IO from application logic.\n- Make processes [idempotent] whenever possible.\n- Separate mutable from immutable data.\n- Avoid trusting data when the cost to validate it is low.\n\n### Development and Testing\n\n- To support rapid development iteration, All system components _must_ be\n  runnable in a single process.\n- Keep the [compile test suite] blazingly fast.\n- In general, prefer in-memory implementations over mocks and stubs.\n- In general, prefer [sociable over solitary tests].\n- Commit messages should describe both what is being changed and why it is\n  being changed.\n\n### Monitoring and Observability\n\n- Make liberal use of [Prometheus metrics] to aid in monitoring and debugging.\n- Follow the Prometheus [metrics naming recommendations].\n\n[ans-104]: https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md\n[docker compose]: https://docs.docker.com/compose/install/\n[envoy]: https://www.envoyproxy.io/\n[bundle schema]: https://ar-io.github.io/ar-io-node/schema/sqlite/bundles/index.html\n[idempotent]: https://en.wikipedia.org/wiki/Idempotence\n[compile test suite]: https://martinfowler.com/bliki/UnitTest.html\n[sociable over solitary tests]: https://martinfowler.com/bliki/UnitTest.html\n[prometheus metrics]: https://github.com/siimon/prom-client\n[metrics naming recommendations]: https://prometheus.io/docs/practices/naming/\n[turbo]: https://github.com/ardriveapp/turbo-upload-service/\n[Dry Runs]: https://github.com/permaweb/ao/blob/main/connect/README.md#dryrun\n[Grafana]: https://grafana.com/\n[Grafana documentation]: https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/view-dashboard-json-model/\n[Prometheus]: https://prometheus.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far-io%2Far-io-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Far-io%2Far-io-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Far-io%2Far-io-node/lists"}