Getting to know database-based scalers: PostgreSQL and MySQL with queries, Redis list length, and MongoDB. Then an introduction to the KEDA HTTP Add-on and HTTPScaledObject for scaling HTTP workloads to zero with request buffering.

In episode 8 we covered scalers for queues and streams — the most popular source of signals. But not every system uses a broker. Many legacy workloads store their "queue" directly in the database: order rows not yet processed, job tables with pending status. In this episode we learn to read those signals through database scalers, then get to know the KEDA HTTP Add-on, which makes scale-to-zero safe for HTTP workloads.
Sometimes a workload's source of truth is a row of data in a database, not a message in a broker. Database scalers execute a query on every polling cycle and use the result as the metric.
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: postgres-auth
spec:
secretTargetRef:
- parameter: connection
name: postgres-secret
key: connection
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: report-worker-scaler
spec:
scaleTargetRef:
name: report-worker
minReplicaCount: 0
maxReplicaCount: 10
triggers:
- type: postgresql
authenticationRef:
name: postgres-auth
metadata:
query: SELECT COUNT(*) FROM pending_reports WHERE status = 'queued'
targetQueryValue: "50"
activationQueryValue: "5"The query runs on every pollingInterval. The result is divided by targetQueryValue to determine the replica count — 120 rows with a target of 50 means 2 replicas. Monitor its status via kubectl get scaledobject -n production.
Identical to PostgreSQL, just change the type and connection parameters — the secretTargetRef pattern stays the same.
- type: mysql
authenticationRef:
name: mysql-auth
metadata:
query: SELECT COUNT(*) FROM invoices WHERE status = 'pending'
targetQueryValue: "100"A Redis list works like a primitive queue: LPUSH adds work, RPOP takes it. KEDA measures the length of that list, using the same secret pattern as PostgreSQL.
- type: redis
authenticationRef:
name: redis-auth
metadata:
listName: thumbnail-jobs
listLength: "5"
activationListLength: "2"MongoDB is scaled based on the number of documents matching a JSON query.
- type: mongodb
authenticationRef:
name: mongodb-auth
metadata:
dbName: app
collection: jobs
query: '{ "status": "queued" }'
queryValue: "20"Database scalers fit best when: the data already lives in a table or collection and migrating to a broker is too expensive; the workload is small and rarely-run batch; or the process can be counted with a lightweight query. On the other hand, avoid them for high-throughput pipelines — brokers like Kafka or Redis Streams remain the primary choice because they're lighter to poll.
Warning
Every polling cycle runs a new query against the database. A slow query or one without an index adds load to the database itself — make sure the filtered columns are indexed and keep pollingInterval bounded so the database doesn't become the autoscaling bottleneck.
The http scaler from episode 7 only reads metrics — it doesn't hold requests. As a result, scale-to-zero for HTTP workloads is risky: with zero pods, incoming requests fail immediately. The KEDA HTTP Add-on solves this by inserting an interceptor in front of the application.
When pods drop to zero, the interceptor stays alive. It holds (buffers) incoming requests, counts them as pending requests, and informs the scaler. Once the pending count crosses the threshold, pods are brought up and the requests are released.
apiVersion: http.keda.sh/v1alpha1
kind: HTTPScaledObject
metadata:
name: web-app
spec:
hosts:
- api.contoh.com
scaleTargetRef:
deployment: web-app
service: web-app-svc
port: 8080
replicas:
min: 0
max: 10
activation: 20
scalingMetric:
targetPendingRequests: 100hosts determines which domains are routed to the interceptor. replicas.activation: 20 means a new pod is brought up from zero when there are 20 pending requests, and targetPendingRequests: 100 targets one pod per 100 requests currently waiting.
Note
HTTPScaledObject requires the KEDA HTTP Add-on, which is installed separately — it's not part of the standard KEDA installation. Without the add-on, this resource is unknown and fails to apply. We'll break down its full architecture in episode 12.
listLength and activationListLength.targetPendingRequests, min, and max.All scalers so far are built into KEDA. In episode 10 we level up: building a gRPC custom scaler for your own internal systems, understanding how KEDA talks to HPA through the External Metrics API, and mixing AND/OR multi-trigger combinations in a single ScaledObject. See you there!