> ## Documentation Index
> Fetch the complete documentation index at: https://powersync-docs-sync-connection-metrics.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring

> Monitor a self-hosted PowerSync Service by scraping metrics from a Prometheus-compatible endpoint.

## Metrics Endpoint

PowerSync exposes instance metrics via a Prometheus-compatible endpoint. This allows you to integrate with Prometheus or other monitoring systems that scrape Prometheus endpoints.

<Note>It's not recommended to scrape the Prometheus endpoint manually, we suggest using Prometheus or other compatible tools. PowerSync does not currently support pushing to OpenTelemetry collectors.</Note>

#### Configuration

1. To enable metrics, update your PowerSync YAML file to include the `prometheus_port` and set a port number.

```yaml service.yaml theme={null}
telemetry:
  # Set the port at which the Prometheus metrics will be exposed
  prometheus_port: 9090
```

2. Update your Docker compose file to forward the `prometheus_port`.

```yaml docker-compose.yaml theme={null}
ports:
  # Forward port 8080 for the PowerSync Service
  - 8080:8080
  # Forward port 9090 for Prometheus metrics
  - 9090:9090
```

Once enabled, restart the service and the metrics endpoint will return Prometheus-formatted metrics, as described in the [What is Collected](/maintenance-ops/self-hosting/usage-reporting#what-is-collected) section of the [Usage Reporting](/maintenance-ops/self-hosting/usage-reporting) docs.

<Note>If you're running multiple containers (e.g. splitting up replication containers and API containers) you need to scrape the metrics separately for each container.</Note>

## Sync Connection Outcomes

`powersync_sync_connections_total` counts sync streams as they close, plus connection attempts the Service rejects before a stream opens. Use it to see whether clients are disconnecting cleanly, failing mid-stream, or being turned away, and why. `powersync_concurrent_connections` remains the gauge for streams that are currently open.

The counter has four labels: `outcome`, `close_reason`, `error_code` and `transport` (`http_stream` or `rsocket`).

| `outcome`  | `close_reason`                                                   | `error_code`                                  |
| ---------- | ---------------------------------------------------------------- | --------------------------------------------- |
| `success`  | `client_closed`, `service_closed`, `process_shutdown`, `unknown` | `none`                                        |
| `error`    | `stream_error`                                                   | PowerSync error code, or `other`              |
| `rejected` | `service_unavailable`                                            | `PSYNC_S2003`                                 |
| `rejected` | `no_sync_config`                                                 | `PSYNC_S2302`                                 |
| `rejected` | `storage_error`                                                  | PowerSync error code, or `other`              |
| `rejected` | `sync_config_error`                                              | PowerSync error code, or `other`              |
| `rejected` | `concurrency_limit`                                              | `PSYNC_S2304` over RSocket, `other` over HTTP |

* `success` means the stream ended without an error. Token expiry, a sync config switch and process shutdown all count as success. It says nothing about whether the client finished syncing.
* `storage_error` and `sync_config_error` are failures to load or parse the active sync config while setting up the stream.
* Over HTTP, `concurrency_limit` returns a bare 429 with no PowerSync error code, so `error_code` is `other`.
* Requests that fail authentication or validation are not counted.

See [Error Codes](/debugging/error-codes) for the meaning of each `PSYNC_` code.

### PromQL Examples

Rate of closes and rejections by outcome:

```promql theme={null}
sum by (outcome, transport) (rate(powersync_sync_connections_total[5m]))
```

Stream errors in the last hour, by code:

```promql theme={null}
sum by (error_code, transport) (
  increase(powersync_sync_connections_total{outcome="error"}[1h])
) > 0
```

Rejected attempts in the last hour, by reason. Anything above zero here is worth alerting on:

```promql theme={null}
sum by (close_reason, transport) (
  increase(powersync_sync_connections_total{outcome="rejected"}[1h])
) > 0
```
