# gRPC RPCs (/integrations/keda/reference/grpc-rpcs)



The scaler implements the four RPCs of KEDA's `ExternalScaler` gRPC service. This page is the
reference for that surface, the single metric it exposes, the bounded retry policy, and the gRPC
health service. For the conceptual model behind these RPCs, see
[Concepts](/integrations/keda/concepts).

## The ExternalScaler RPCs [#the-externalscaler-rpcs]

All four RPCs parse trigger metadata first and return `InvalidArgument` on a bad spec before
touching KubeMQ.

| RPC              | Purpose                                                                                                                                                  | Source                                                                                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IsActive`       | Returns `true` when `Waiting > activationTargetWaiting`.                                                                                                 | Reads the live `Waiting` count, compares to `activationTargetWaiting`.                                                                                  |
| `StreamIsActive` | Server-streaming. Sends the current active status immediately, then re-evaluates and pushes on a fixed `5s` ticker until the client context is canceled. | Used by `external-push`. A poll failure mid-stream is logged and skipped (the stream stays open); the initial poll failure returns a mapped gRPC error. |
| `GetMetricSpec`  | Returns the target value for the `kubemq-queue-waiting` metric, set from `targetWaiting`.                                                                | No KubeMQ call; pure metadata.                                                                                                                          |
| `GetMetrics`     | Returns the current `Waiting` count as the value of `kubemq-queue-waiting`.                                                                              | Reads the live `Waiting` count.                                                                                                                         |

## The single metric [#the-single-metric]

The scaler exposes exactly one metric:

| Metric Name            | Source                                                                                                                                        |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `kubemq-queue-waiting` | The queue channel's `Outgoing.Waiting` count, obtained via `client.ListQueuesChannels(queueName)` and matched on `Channel.Name == queueName`. |

`GetMetrics` rejects any `MetricName` other than `kubemq-queue-waiting` with `InvalidArgument`, and
rejects a request with a nil `ScaledObjectRef` the same way.

<Mermaid
  chart="`
sequenceDiagram
  participant K as KEDA Operator
  participant S as kubemq-keda-scaler
  participant B as KubeMQ Broker
  K->>S: GetMetricSpec (target = targetWaiting)
  K->>S: IsActive / GetMetrics
  S->>B: ListQueuesChannels(queueName)
  B-->>S: channels[].Outgoing.Waiting
  S-->>K: Waiting count (kubemq-queue-waiting)
  Note over K,S: external-push: StreamIsActive pushes every 5s
`"
/>

*KEDA reads the target once via `GetMetricSpec`, then polls `IsActive` / `GetMetrics`; the scaler answers each by reading the queue's `Waiting` count from the broker.*

## Retry behavior [#retry-behavior]

`GetMetrics`, `IsActive`, and the per-tick polls inside `StreamIsActive` all route through a single
`getWaiting` helper that applies a small, bounded retry policy:

* **Up to 2 attempts** (`getWaitingMaxRetries = 2`).
* A **200ms delay** between attempts (`getWaitingRetryDelay`), itself cancelable by the request context.
* Retries fire **only** when the mapped status code is `Unavailable` or `DeadlineExceeded` — the transient classes. Any other code (e.g. `Unauthenticated`, `InvalidArgument`, `NotFound`) returns immediately without retrying.
* **Before the final retry**, the pooled connection for that metadata is **evicted** (`pool.Evict(meta)`), so the last attempt forces a fresh connection rather than reusing a possibly-dead one.

If all attempts fail, the last mapped error is returned to KEDA. The full mapping lives in the
[error-codes reference](/integrations/keda/reference/error-codes).

## Health checks [#health-checks]

The scaler registers a standard gRPC **Health** service (`grpc.health.v1.Health`) on the *same*
port as the `ExternalScaler` service. The Helm deployment wires both the liveness and readiness
probes to native gRPC health checks.

<Callout type="info">
  Both probes check **gRPC server health only** — they do **not** verify KubeMQ broker connectivity.
  A scaler reporting `SERVING` means its gRPC server is up, not that the broker is reachable. Broker
  reachability surfaces instead through the per-RPC error mapping and KEDA's `fallback`.
</Callout>

```yaml title="deployment.yaml (probes)"
livenessProbe:
  grpc:
    port: 9090
  initialDelaySeconds: 5
  periodSeconds: 10
readinessProbe:
  grpc:
    port: 9090
  initialDelaySeconds: 5
  periodSeconds: 10
```

Native gRPC probes require &#x2A;*Kubernetes 1.27+**. You can exercise the health endpoint manually:

```bash title="Manual health check"
kubectl port-forward svc/kubemq-keda-scaler 9090:9090
grpcurl -plaintext localhost:9090 grpc.health.v1.Health/Check
```

A healthy scaler responds:

```json
{
  "status": "SERVING"
}
```

## Related [#related]

* [Concepts](/integrations/keda/concepts) — the external-scaler protocol and trigger types.
* [Error codes](/integrations/keda/reference/error-codes) — how KubeMQ errors map to gRPC status codes.
* [ScaledObject metadata](/integrations/keda/reference/scaled-object-metadata) — the trigger metadata each RPC parses.
