> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blnkfinance.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring in Blnk

> Monitor and debug Blnk Core with logs, traces, and metrics in Blnk Cloud or your own stack.

export const CtaCallout = props => {
  const {title, buttonLabel, href, trackingEvent, buttonTarget, rel = "noopener noreferrer", children} = props;
  const handleCtaClick = () => {
    if (typeof window === "undefined" || !trackingEvent) {
      return;
    }
    try {
      window.dispatchEvent(new CustomEvent("blnk:docs-cta", {
        detail: {
          name: trackingEvent,
          href
        }
      }));
    } catch {}
    try {
      window.posthog?.capture?.(trackingEvent, {
        href
      });
    } catch {}
    const gaPayload = {
      cta_href: href
    };
    try {
      window.gtag?.("event", trackingEvent, gaPayload);
    } catch {}
    try {
      window.dataLayer = window.dataLayer || [];
      window.dataLayer.push({
        event: trackingEvent,
        ...gaPayload
      });
    } catch {}
  };
  const isExternal = typeof href === "string" && (/^https?:\/\//i).test(href);
  const target = buttonTarget ?? (isExternal ? "_blank" : undefined);
  const linkRel = isExternal ? rel : undefined;
  return <section className="cta-callout not-prose relative my-8 w-full min-w-0 overflow-hidden rounded-xl border border-zinc-200 p-5 dark:border-white/10">
      <div className="cta-callout-noise" aria-hidden="true" />
      <div className="cta-callout-layout">
        {title ? <div className="cta-callout-title-row">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="14" height="14" className="cta-callout-icon shrink-0 text-zinc-800 dark:text-zinc-200" aria-hidden="true">
              <g fill="none" fillRule="nonzero">
                <path d="M28 0v28H0V0h28ZM14.691833333333335 27.134333333333334l-0.012833333333333334 0.0023333333333333335 -0.08283333333333333 0.04083333333333334 -0.023333333333333334 0.004666666666666667 -0.016333333333333335 -0.004666666666666667 -0.08283333333333333 -0.04083333333333334c-0.011666666666666667 -0.004666666666666667 -0.022166666666666668 -0.0011666666666666668 -0.028000000000000004 0.005833333333333334l-0.004666666666666667 0.011666666666666667 -0.019833333333333335 0.49933333333333335 0.005833333333333334 0.023333333333333334 0.011666666666666667 0.015166666666666667 0.12133333333333333 0.08633333333333333 0.0175 0.004666666666666667 0.014000000000000002 -0.004666666666666667 0.12133333333333333 -0.08633333333333333 0.014000000000000002 -0.018666666666666668 0.004666666666666667 -0.019833333333333335 -0.019833333333333335 -0.4981666666666667c-0.0023333333333333335 -0.011666666666666667 -0.0105 -0.019833333333333335 -0.019833333333333335 -0.021Zm0.3091666666666667 -0.13183333333333336 -0.015166666666666667 0.0023333333333333335 -0.21583333333333335 0.1085 -0.011666666666666667 0.011666666666666667 -0.0035000000000000005 0.012833333333333334 0.021 0.5016666666666667 0.005833333333333334 0.014000000000000002 0.009333333333333334 0.008166666666666668 0.23450000000000004 0.1085c0.014000000000000002 0.004666666666666667 0.026833333333333334 0 0.03383333333333334 -0.009333333333333334l0.004666666666666667 -0.016333333333333335 -0.03966666666666667 -0.7163333333333334c-0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.023333333333333334 -0.023333333333333334 -0.025666666666666667Zm-0.8341666666666667 0.0023333333333333335a0.026833333333333334 0.026833333333334334 0 0 0 -0.0315 0.007000000000000001l-0.007000000000000001 0.016333333333333335 -0.03966666666666667 0.7163333333333334c0 0.014000000000000002 0.008166666666666668 0.023333333333333334 0.019833333333333335 0.028000000000000004l0.0175 -0.0023333333333333335 0.23450000000000004 -0.1085 0.011666666666666667 -0.009333333333333334 0.004666666666666667 -0.012833333333333334 0.019833333333333335 -0.5016666666666667 -0.0035000000000000005 -0.014000000000000002 -0.011666666666666667 -0.011666666666666667 -0.21466666666666667 -0.10733333333333334Z" strokeWidth="1.1667" />
                <path fill="currentColor" d="M14 2.916666666666667A1.75 1.75 0 0 1 15.750000000000002 4.666666666666667v6.302333333333334L21.207666666666668 7.816666666666667a1.75 1.75 0 0 1 1.75 3.031L17.5 14l5.457666666666667 3.151166666666667a1.75 1.75 0 0 1 -1.75 3.031l-5.457666666666667 -3.1500000000000004V23.333333333333336a1.75 1.75 0 0 1 -3.5 0v-6.302333333333334L6.792333333333334 20.183333333333337a1.75 1.75 0 1 1 -1.75 -3.031L10.5 14 5.042333333333334 10.848833333333333a1.75 1.75 0 0 1 1.75 -3.031l5.457666666666667 3.1500000000000004V4.666666666666667A1.75 1.75 0 0 1 14 2.916666666666667Z" strokeWidth="1.1667" />
              </g>
            </svg>
            <p className="cta-callout-title min-w-0 font-semibold text-zinc-800 dark:text-zinc-200">
              {title}
            </p>
          </div> : null}
        <div className={`cta-callout-body text-sm leading-normal text-zinc-800 dark:text-zinc-200${title ? " cta-callout-body--indented" : ""}`}>
          {children}
        </div>
        <a href={href} target={target} rel={linkRel} onClick={handleCtaClick} data-docs-cta={trackingEvent || undefined} className="cta-callout-button inline-flex items-center justify-center gap-1 rounded-full bg-white px-3 py-1.5 text-sm font-semibold transition hover:bg-zinc-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/50 dark:bg-white dark:hover:bg-zinc-200">
          {buttonLabel}
          <span className="cta-callout-button-arrow" aria-hidden="true">
            →
          </span>
        </a>
      </div>
    </section>;
};

Running a ledger means caring about correctness, latency, and throughput.

Monitoring shows whether Blnk is healthy and where problems show up, without inferring system state from API responses alone.

This guide helps you set up monitoring for your Core. For configuration flags, see [Observability configuration](/advanced/configuration/observability).

***

## Quick setup: Blnk Cloud

<Info>Requires Blnk Core 0.14.4 or later.</Info>

When something breaks in your production ledger, you need to see what happened: which request failed, where time was spent, etc.

Waiting on another team for logs slows that down and creates bottlenecks.

<Frame>
  <img src="https://mintcdn.com/blnk/h-WoCOA8jqx3DHPU/cloud/img/monitoring/cloud-logs.png?fit=max&auto=format&n=h-WoCOA8jqx3DHPU&q=85&s=cb534e3665ee68cb649046f783922a5d" alt="Blnk Cloud monitoring workspace showing log lines from the server and worker" width="3420" height="2146" data-path="cloud/img/monitoring/cloud-logs.png" />
</Frame>

Blnk Cloud includes built-in monitoring for your ledger. No Jaeger or Prometheus setup required.

Simply connect your Core instance via a Blnk Cloud DSN and you can start viewing logs, traces, and metrics in the same workspace where you manage your ledger operations.

To get started:

<Steps>
  <Step title="Sign in to Blnk Cloud">
    Open your [Blnk Cloud](https://cloud.blnkfinance.com) workspace.
  </Step>

  <Step title="Connect your instance">
    If you have not already, connect your Core deployment to Cloud.

    For a self-hosted Core, follow [Connect your self-hosted Core](/cloud/instances/create). For a managed instance, see [Deploy a managed instance](/cloud/instances/deploy).
  </Step>

  <Step title="Enable monitoring and copy the DSN">
    Open the instance in Cloud, turn on monitoring in the instance settings, then copy the `Blnk Cloud DSN`.

    You will add it to your Core configuration in the next step.

    <Frame>
      <img src="https://mintcdn.com/blnk/O7pFuUzrwI59POw5/cloud/img/instances/instance-monitoring-dsn.png?fit=max&auto=format&n=O7pFuUzrwI59POw5&q=85&s=9f05e9e5caf4f16c437ab90610ac0ce3" alt="Blnk Cloud instance settings with monitoring enabled and the Blnk Cloud DSN field visible" width="3420" height="2146" data-path="cloud/img/instances/instance-monitoring-dsn.png" />
    </Frame>
  </Step>

  <Step title="Set the Blnk Cloud DSN in your Core config">
    Turn on observability and add the Blnk Cloud DSN to your configuration file.

    <CodeGroup>
      ```bash blnk.env wrap theme={"system"}
      BLNK_ENABLE_OBSERVABILITY=true
      BLNK_CLOUD_DSN=https://<write-key>@observe.blnk.cloud/<project-id>
      ```

      ```json blnk.json wrap theme={"system"}
      {
        "enable_observability": true,
        "cloud_dsn": "https://<write-key>@observe.blnk.cloud/<project-id>"
      }
      ```
    </CodeGroup>

    Restart the server and worker processes after updating configuration.
  </Step>

  <Step title="Confirm data is flowing">
    Check server logs for a message that monitoring export is enabled, then open your Blnk Cloud monitoring workspace and confirm Blnk data is arriving.

    It may take a few minutes for the first data to show up.

    <Frame>
      <img src="https://mintcdn.com/blnk/h-WoCOA8jqx3DHPU/cloud/img/monitoring/cloud-traces.png?fit=max&auto=format&n=h-WoCOA8jqx3DHPU&q=85&s=ea2cf704bf93009f6408db95b314fdc1" alt="Blnk Cloud monitoring workspace showing a distributed trace timeline" width="3420" height="2146" data-path="cloud/img/monitoring/cloud-traces.png" />
    </Frame>

    <Note>
      When you export to Blnk Cloud, sensitive values (such as tokens and connection strings) are removed before they leave your instance.
    </Note>
  </Step>
</Steps>

***

## Connect to other tools

If your team already runs a dedicated observability stack, you can export Blnk logs, traces, and metrics to Jaeger, Prometheus, Grafana, OpenTelemetry Collector, Datadog, or any backend you operate.

Blnk exposes traces and metrics via OpenTelemetry and Prometheus. Logs are written to process output; forward them with your log shipper.

<Steps>
  <Step title="Enable observability in Core">
    Set `BLNK_ENABLE_OBSERVABILITY=true` on the server and workers.

    <CodeGroup>
      ```bash blnk.env wrap theme={"system"}
      BLNK_ENABLE_OBSERVABILITY=true
      ```

      ```json blnk.json wrap theme={"system"}
      {
        "enable_observability": true
      }
      ```
    </CodeGroup>

    Restart both processes after updating configuration.
  </Step>

  <Step title="Export logs">
    Collect `stdout` and `stderr` with your log agent or shipper and forward to any backend.
  </Step>

  <Step title="Export traces">
    Set the traces OTLP HTTP endpoint in the environment for the server and worker. Jaeger, Grafana Tempo, and the OpenTelemetry Collector accept OTLP:

    ```bash blnk.env wrap theme={"system"}
    OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://jaeger:4318
    ```

    After restart, call any API endpoint and confirm traces for service `BLNK` appear in your backend (Jaeger UI defaults to port `16686`).
  </Step>

  <Step title="Export metrics">
    Blnk supports two export modes. Use one or both.

    <Tabs>
      <Tab title="Pull">
        Scrape `GET /metrics` from the server and worker. Targets depend on your setup:

        | Setup                                                | Server target           | Worker target           |
        | :--------------------------------------------------- | :---------------------- | :---------------------- |
        | [Docker Compose](/home/deploy#setting-up-monitoring) | `server:5001`           | `worker:5004`           |
        | Local Prometheus                                     | `localhost:5001`        | `localhost:5004`        |
        | Managed service                                      | Your server metrics URL | Your worker metrics URL |

        <CodeGroup>
          ```yaml No auth wrap theme={"system"}
          scrape_configs:
            - job_name: blnk-server
              metrics_path: /metrics
              static_configs:
                - targets: ["server:5001"]

            - job_name: blnk-worker
              metrics_path: /metrics
              static_configs:
                - targets: ["worker:5004"]
          ```

          ```yaml Auth enabled wrap theme={"system"}
          scrape_configs:
            - job_name: blnk-server
              metrics_path: /metrics
              static_configs:
                - targets: ["server:5001"]
              authorization:
                type: Bearer
                credentials: "<metrics-bearer-token>"

            - job_name: blnk-worker
              metrics_path: /metrics
              static_configs:
                - targets: ["worker:5004"]
              authorization:
                type: Bearer
                credentials: "<metrics-bearer-token>"
          ```
        </CodeGroup>

        <Warning>
          `/metrics` never accepts `X-Blnk-Key`. Set the [metrics bearer token](/advanced/configuration/server-security#metrics-endpoint) in Core before using the Auth enabled scrape config.
        </Warning>

        <CodeGroup>
          ```bash blnk.env wrap theme={"system"}
          BLNK_METRICS_BEARER_TOKEN=<metrics-bearer-token>
          ```

          ```json blnk.json wrap theme={"system"}
          {
            "server": {
              "metrics_bearer_token": "<metrics-bearer-token>"
            }
          }
          ```
        </CodeGroup>

        Restart both processes after changing the token. Verify scrapes against each target:

        <CodeGroup>
          ```bash No auth wrap theme={"system"}
          curl -X GET "http://localhost:5001/metrics"

          curl -X GET "http://localhost:5004/metrics"
          ```

          ```bash Auth enabled wrap theme={"system"}
          curl -X GET "http://localhost:5001/metrics" \
            -H "Authorization: Bearer <metrics-bearer-token>"

          curl -X GET "http://localhost:5004/metrics" \
            -H "Authorization: Bearer <metrics-bearer-token>"
          ```
        </CodeGroup>
      </Tab>

      <Tab title="Push">
        Set `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` to send metrics over `OTLP HTTP` to an OpenTelemetry Collector or compatible backend.

        Blnk pushes on a 60-second interval.

        ```bash blnk.env wrap theme={"system"}
        OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://otel-collector:4318
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Confirm each signal">
    After restart and a test API call, verify monitoring export is working end to end. Server and worker logs should report that monitoring export is active.

    ```bash wrap theme={"system"}
    curl http://localhost:5001/health
    curl http://localhost:5004/health
    ```

    <CodeGroup>
      ```json Server 200 OK wrap theme={"system"}
      {
        "status": "UP"
      }
      ```

      ```json Worker 200 OK wrap theme={"system"}
      {
        "status": "UP",
        "service": "worker"
      }
      ```
    </CodeGroup>

    Probe metrics on both processes (omit the header when no bearer token is configured):

    ```bash wrap theme={"system"}
    curl -H "Authorization: Bearer <metrics-bearer-token>" http://localhost:5001/metrics | grep blnk_

    curl -H "Authorization: Bearer <metrics-bearer-token>" http://localhost:5004/metrics | grep blnk_
    ```

    Check traces in your OTLP backend and log lines in your log store.
  </Step>
</Steps>

***

## Common Blnk scenarios

Match the symptom to the signal that answers it fastest. Start with the recommended signal, then drill into the others if you still need context.

<AccordionGroup>
  <Accordion title="API feels slow">
    **Start with:** Traces

    Open a trace for a slow request and compare step duration across the timeline. Look for time spent in database writes, queue enqueue, or external calls rather than assuming the API handler is the bottleneck.

    If traces are unavailable, check server logs for the request window and correlate with queue processing logs on the worker.
  </Accordion>

  <Accordion title="Transactions stuck in QUEUED">
    **Start with:** Logs and [queue monitoring](/advanced/monitoring-port)

    Confirm workers are running and processing jobs. In the queue dashboard, check depth and whether items are moving.

    In logs, look for worker startup messages, processing errors, or repeated retries on the same transaction. A healthy queue should show enqueue activity on the server and dequeue/processing activity on workers.
  </Accordion>

  <Accordion title="Ledger integrity or processing delay">
    **Start with:** Metrics

    Watch background processing signals over time. Rising processing duration or falling throughput can mean hash-chain sealing or related integrity work is falling behind.

    Compare server and worker metrics together. Delay on the worker while the API looks healthy often points to queue backlog rather than API saturation.
  </Accordion>

  <Accordion title="Errors or 5xx spikes">
    **Start with:** Logs, then traces

    Filter logs around the spike window and capture the error message and `transaction_id` or request ID when present. That gives you the failure reason without opening a trace first.

    When you need timing context, open the trace for the same request and see which step returned the error or timed out.
  </Accordion>

  <Accordion title="Rejection rate spike">
    **Start with:** Metrics, then logs

    Check rejection counters grouped by reason (for example insufficient funds, overdraft limit, lock contention). A sudden change in one reason usually narrows the investigation quickly.

    Use logs to find example rejected transactions and confirm whether the spike matches a product change, balance issue, or concurrency pattern.
  </Accordion>

  <Accordion title="Worker retries climbing">
    **Start with:** Metrics and logs

    Sustained worker retries often mean transactions are failing transiently or hitting lock contention. Compare retry rate with queue processing duration on the worker.

    In logs, search for retry messages on the worker and note the error text. Repeated retries on the same balance pair may indicate hot-lane or lock contention worth correlating with transaction volume.
  </Accordion>

  <Accordion title="Inflight commit or void not completing">
    **Start with:** Logs, then traces

    Find the inflight transaction ID in logs and follow commit or void processing on the worker. Confirm the original inflight transaction exists and the follow-up request reached Core.

    If processing started but did not finish, use a trace on the commit or void request to see whether failure happened in validation, balance update, or queue handling.
  </Accordion>

  <Accordion title="After a deploy, latency or errors increased">
    **Start with:** Traces and metrics

    Compare request latency and error rate before and after the deploy window. Open traces for representative slow and failed requests in each window and note which step changed.

    Check that both server and worker were restarted with the same monitoring export and configuration changes. Mismatched config between processes is a common post-deploy regression.
  </Accordion>

  <Accordion title="Monitoring data not showing up">
    **Start with:** Logs

    After restart, server logs should report that monitoring export is enabled. For Blnk Cloud, confirm monitoring is on in the instance settings and the Blnk Cloud DSN is set. For self-hosted export, confirm OTLP or scrape targets are configured on **both** server and worker.

    Cloud ingestion can take a few minutes for the first data. For self-hosted setups, send a test API request and check your trace backend, metrics scraper, and log store separately.
  </Accordion>

  <Accordion title="/metrics returns 404">
    Monitoring export is disabled or the process was not restarted after enabling it.

    Set `enable_observability=true` on the server and worker, then restart both processes.
  </Accordion>

  <Accordion title="/metrics returns 403">
    [Secure mode](/advanced/configuration/server-security#secure-mode) is on but `metrics_bearer_token` is not set.

    Configure a bearer token and restart Core.
  </Accordion>

  <Accordion title="/metrics returns 401">
    A bearer token is required but missing or invalid. Include `Authorization: Bearer <token>` in scrape or curl requests.
  </Accordion>

  <Accordion title="No traces in Jaeger">
    Blnk exports traces over OTLP HTTP.

    Confirm `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` is set on both server and worker. Use port **4318** for OTLP HTTP, not gRPC port 4317.
  </Accordion>

  <Accordion title="Queue dashboard works but metrics do not">
    The queue dashboard is at `/monitoring` on the worker port. Metrics are at `/metrics` on the server and worker ports. Monitoring export must be enabled for `/metrics` to be registered.
  </Accordion>

  <Accordion title="Production health baseline">
    **Start with:** Metrics

    Establish normal ranges for resource use, transaction throughput, queue processing time, and rejection rate during steady traffic. Use those baselines for alerts rather than fixed thresholds copied from another environment.

    Confirm scrapes or Cloud ingestion succeed on a schedule so gaps in data do not look like an incident.
  </Accordion>
</AccordionGroup>

***

## Related docs

<CardGroup cols={2}>
  <Card title="Observability configuration" icon="activity" href="/advanced/configuration/observability">
    Flags and environment variables.
  </Card>

  <Card title="Metrics reference" icon="chart-line" href="/advanced/metrics-reference">
    Full Prometheus metric catalog.
  </Card>

  <Card title="Queue monitoring" icon="radio" href="/advanced/monitoring-port">
    Queue dashboard and worker port.
  </Card>

  <Card title="Deploy Blnk" icon="rocket" href="/home/deploy">
    Docker deployment and optional monitoring export.
  </Card>
</CardGroup>

***

## Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool.

To ask questions or discuss issues, please [contact us](mailto:support@blnkfinance.com) or [join our Discord community](https://discord.gg/7WNv94zPpx).

<CtaCallout title="Connect your ledger to Blnk Cloud" href="https://cloud.blnkfinance.com/auth/sign-up?utm_source=blnk_docs&utm_medium=documentation&utm_campaign=need-help" buttonLabel="Open Blnk Cloud" trackingEvent="clicked_cloud_signup">
  Sign up and manage your ledger with our back-office dashboard. You can invite teammates to collaborate and manage your ledger operations directly from the dashboard.
</CtaCallout>
