# ScaledObject Metadata (/integrations/keda/reference/scaled-object-metadata)



This is the authoritative reference for the `ScaledObject` configuration that drives the
**KubeMQ KEDA external scaler** (`kubemq/kubemq-keda-scaler:1.0.0`). It documents every trigger
metadata field, the scaler Service address, the two trigger types, the Helm values, and the
example manifests the repo ships. For the metric's underlying meaning, see [Queues](/learn/queues);
for the scaler's own process settings, see [Environment variables](/integrations/keda/reference/environment-variables).

## Trigger metadata [#trigger-metadata]

Every field below is read from the `metadata` block of a KEDA `external` (or `external-push`)
trigger and parsed by `ParseScalerMetadata`. Required fields produce an `InvalidArgument` gRPC
error if absent; bounds are enforced on length and numeric range.

| Parameter                 | Required | Default | Description                                                                                                                                             |
| ------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kubemqAddress`           | Yes      | —       | KubeMQ broker address in `host:port` form. Max 253 characters; the port must be `1`–`65535`. Parsed with `net.SplitHostPort`.                           |
| `queueName`               | Yes      | —       | Queue channel name to monitor. Max 256 characters.                                                                                                      |
| `targetWaiting`           | No       | `10`    | Target `Waiting` messages per replica. Must be a finite, positive number.                                                                               |
| `activationTargetWaiting` | No       | `0`     | Scale-from-zero threshold. The scaler reports active when `Waiting > activationTargetWaiting`. Must be a finite, non-negative number.                   |
| `authToken`               | No       | —       | KubeMQ authentication token. Max 4096 characters. Supply via a `TriggerAuthentication` secret rather than inline.                                       |
| `tls`                     | No       | `false` | Enable a TLS connection to KubeMQ. Accepts `true`, `1`, or `yes` (case-insensitive) as true; anything else is false.                                    |
| `certFile`                | No       | —       | Path to a CA certificate file. Max 512 characters. Must resolve under `/certs/`, `/etc/ssl/`, or `/etc/pki/`, and must not contain `..` path traversal. |
| `serverOverrideDomain`    | No       | —       | TLS server-name override (SNI) for the KubeMQ connection.                                                                                               |

<Callout type="info">
  `scalerAddress` is consumed by KEDA itself (it tells KEDA where to reach the scaler) and is **not**
  part of the scaler's own metadata schema. The fields above are what the scaler parses from each RPC.
  The `authToken`, `tls`, `certFile`, `serverOverrideDomain`, and `kubemqAddress` values also form the
  connection-pool key, so distinct combinations get distinct pooled connections.
</Callout>

The numeric defaults and bounds are enforced, not advisory. A `targetWaiting` of `0`, `-1`, `NaN`,
or `Inf` is rejected with `InvalidArgument`, as is a non-numeric string. Always quote numeric values
(`"10"`, `"5"`, `"1"`) since trigger metadata is a string map.

```yaml title="scaled-object-basic.yaml"
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kubemq-queue-scaler
spec:
  scaleTargetRef:
    name: my-queue-consumer
  pollingInterval: 15
  cooldownPeriod: 60
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
    - type: external
      metadata:
        scalerAddress: kubemq-keda-scaler.default.svc.cluster.local:9090
        kubemqAddress: kubemq.default.svc.cluster.local:50000
        queueName: my-queue
        targetWaiting: "10"
```

## Scaler Service address [#scaler-service-address]

The `scalerAddress` in your `ScaledObject` must resolve to the scaler's Kubernetes `Service`.
Because the scaler runs as a `ClusterIP` service on port `9090`, use the cluster-internal FQDN:

```text title="FQDN format"
<service-name>.<namespace>.svc.cluster.local:9090
```

The service name follows the Helm release name. For a release named `my-release` installed into
namespace `keda`:

```text title="Helm release example"
my-release-kubemq-keda-scaler.keda.svc.cluster.local:9090
```

For the default Helm install (release name `kubemq-keda-scaler` in namespace `default`), the
address is `kubemq-keda-scaler.default.svc.cluster.local:9090`.

## Trigger types [#trigger-types]

KEDA supports two external trigger types against the same scaler. They differ only in how KEDA
drives the scaler, not in what it measures. See [Concepts](/integrations/keda/concepts) for
the model.

| Type            | Mode                 | Behavior                                                                                                                                                                    |
| --------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `external`      | Poll-based (default) | KEDA calls `IsActive` and `GetMetrics` every `pollingInterval` seconds.                                                                                                     |
| `external-push` | Push-based           | KEDA opens a long-lived `StreamIsActive` stream. The scaler pushes active-status updates independently of `pollingInterval`. Use this for faster scale-from-zero detection. |

```yaml title="scaled-object-scale-to-zero.yaml (external-push)"
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: scale-to-zero-scaler
spec:
  scaleTargetRef:
    name: batch-processor
  pollingInterval: 10
  cooldownPeriod: 120
  minReplicaCount: 0
  maxReplicaCount: 5
  triggers:
    - type: external-push
      metadata:
        scalerAddress: <SCALER_SERVICE>.<NAMESPACE>.svc.cluster.local:9090
        kubemqAddress: kubemq.default.svc.cluster.local:50000
        queueName: batch-jobs
        targetWaiting: "1"
        activationTargetWaiting: "0"
```

## Helm values [#helm-values]

The chart (`kubemq-keda-scaler`, chart version `1.0.0`, app version `1.0.0`) ships production-safe
defaults: a hardened `securityContext`, modest resource bounds, and a `ClusterIP` service.

| Value                | Default                      | Description                                          |
| -------------------- | ---------------------------- | ---------------------------------------------------- |
| `replicaCount`       | `1`                          | Number of scaler pods.                               |
| `image.repository`   | `kubemq/kubemq-keda-scaler`  | Scaler image.                                        |
| `image.tag`          | `1.0.0`                      | Image tag.                                           |
| `image.pullPolicy`   | `IfNotPresent`               | Image pull policy.                                   |
| `service.type`       | `ClusterIP`                  | Service type (cluster-internal by design).           |
| `service.port`       | `9090`                       | gRPC service port.                                   |
| `env.grpcPort`       | `9090`                       | Maps to `GRPC_PORT`.                                 |
| `env.logLevel`       | `info`                       | Maps to `LOG_LEVEL`.                                 |
| `resources.requests` | `cpu: 50m`, `memory: 64Mi`   | Resource requests.                                   |
| `resources.limits`   | `cpu: 200m`, `memory: 128Mi` | Resource limits.                                     |
| `securityContext`    | hardened (see below)         | Pod/container security hardening.                    |
| `extraVolumes`       | `[]`                         | Extra volumes (e.g. a TLS CA secret).                |
| `extraVolumeMounts`  | `[]`                         | Extra volume mounts (e.g. mount the CA at `/certs`). |

```yaml title="values.yaml (securityContext)"
securityContext:
  runAsNonRoot: true
  runAsUser: 65532
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop:
      - ALL
```

Because `readOnlyRootFilesystem` is `true` and the container runs as UID `65532`, any TLS CA you
mount via `extraVolumes` / `extraVolumeMounts` must land under one of the allowed `certFile`
prefixes (`/certs/`, `/etc/ssl/`, `/etc/pki/`) and be readable by that user. See
[TLS and Authentication](/integrations/keda/how-to/tls-and-auth) for the full flow.

## Example manifests [#example-manifests]

The `deploy/examples/` directory contains ready-to-use manifests. Apply them in the order below,
honoring each file's prerequisites. Replace the `<SCALER_SERVICE>` and `<NAMESPACE>` placeholders
with your actual scaler `Service` name and namespace.

| File                               | Description                                           | Prerequisites                            |
| ---------------------------------- | ----------------------------------------------------- | ---------------------------------------- |
| `trigger-auth.yaml`                | `TriggerAuthentication` plus the referenced `Secret`. | Create or edit the `Secret` token first. |
| `scaled-object-basic.yaml`         | Basic queue autoscaling (`external`).                 | —                                        |
| `scaled-object-ml-inference.yaml`  | GPU inference with scale-to-zero and `fallback`.      | —                                        |
| `scaled-object-scale-to-zero.yaml` | Push-mode (`external-push`) scale-to-zero.            | —                                        |
| `scaled-object-tls-auth.yaml`      | TLS plus auth token.                                  | `trigger-auth.yaml` applied first.       |
| `scaled-job.yaml`                  | `ScaledJob` — one `Job` per batch of messages.        | —                                        |

```yaml title="trigger-auth.yaml"
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: kubemq-trigger-auth
spec:
  secretTargetRef:
    - parameter: authToken
      name: kubemq-auth-secret
      key: token
---
apiVersion: v1
kind: Secret
metadata:
  name: kubemq-auth-secret
type: Opaque
stringData:
  token: "your-kubemq-auth-token"
```

```yaml title="scaled-job.yaml"
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
  name: kubemq-batch-job
spec:
  jobTargetRef:
    template:
      spec:
        containers:
          - name: worker
            image: my-batch-worker:latest
            env:
              - name: KUBEMQ_ADDRESS
                value: kubemq.default.svc.cluster.local:50000
              - name: QUEUE_NAME
                value: batch-queue
        restartPolicy: Never
    backoffLimit: 3
  pollingInterval: 10
  maxReplicaCount: 50
  successfulJobsHistoryLimit: 5
  failedJobsHistoryLimit: 3
  triggers:
    - type: external
      metadata:
        scalerAddress: <SCALER_SERVICE>.<NAMESPACE>.svc.cluster.local:9090
        kubemqAddress: kubemq.default.svc.cluster.local:50000
        queueName: batch-queue
        targetWaiting: "1"
```

## Related [#related]

* [Environment variables](/integrations/keda/reference/environment-variables) — the scaler process settings.
* [gRPC RPCs](/integrations/keda/reference/grpc-rpcs) — the `ExternalScaler` RPC surface, retry, and health checks.
* [Error codes](/integrations/keda/reference/error-codes) — the KubeMQ-error-to-gRPC mapping and KEDA `fallback`.
