I wrote the longer version, with more on each domain, on my blog.
PromQL is 28% of the Prometheus Certified Associate exam, and it's the domain that fails people. I've seen engineers who run Prometheus in production every day pick the wrong function under exam pressure, and I was almost one of them.
I passed with 82 out of 100 on the first attempt. Passing is 75, and most of the points I nearly lost were on things I thought I already knew from work.
Format and domains
From the Linux Foundation curriculum: around 60 multiple choice questions, 90 minutes, 75% to pass, online proctored, no hands-on part.
| Domain | Weight |
|---|---|
| PromQL | 28% |
| Prometheus Fundamentals | 20% |
| Observability Concepts | 18% |
| Alerting and Dashboarding | 18% |
| Instrumentation and Exporters | 16% |
After PromQL the weights are flat. Fundamentals plus Observability is 38%, Instrumentation plus Alerting another 34%. There's no throwaway domain.
Underneath it all, the PCA checks whether you understand the data model: Prometheus is a time series database where every metric is a set of labeled samples. If that feels abstract, PromQL will feel random.
PromQL
The exam hands you an expression and asks for the output, or describes a scenario and asks which expression matches. You only get good at that by writing queries.
The classic trap is rate() vs irate(), placed side by side and written to look interchangeable:
rate(http_requests_total[5m]) # per-second average over the full 5m window
irate(http_requests_total[5m]) # only the last 2 samples
rate() smooths short spikes, which is what you want for alerts and dashboards. irate() reacts instantly and is jumpy. A question describes a brief spike and asks which function reflects it: irate() shows the jump, rate() averages it away. I used rate() at work for years and had never checked how irate() differs until I studied.
Label matchers are everywhere:
-
{job="node_exporter"}is an exact match -
{job=~"node.*"}is a regex match -
{job!~".*test.*"}excludes anything containing "test"
sum(http_requests_total) by (job) keeps only the job label. sum(http_requests_total) without (instance) drops instance and keeps the rest. The questions hinge on which labels survive, so sketch the label set before and after on scratch paper.
histogram_quantile() needs a _bucket series with an le label. I think it's the one advanced function worth running once against real data.
Fundamentals
Prometheus pulls. It scrapes targets on an interval, and push vs pull came up more than once. The Pushgateway is the narrow exception for short-lived batch jobs that finish before a scrape. Using it as a general push endpoint for long-running services leaves stale metrics behind, and the exam tests that distinction.
Kubernetes service discovery is on there too. Remember relabeling: it turns the raw discovery labels into the final label set on your metrics.
Metric types
The four metric types were the most common non-PromQL topic I saw:
- Counter only goes up and resets on restart. You wrap it in rate(), which is why rate() exists.
- Gauge goes up and down. Read it directly.
-
Histogram exposes
_bucket,_sumand_count, and the quantile is calculated on the server at query time, so it aggregates across instances. - Summary calculates quantiles on the client, and those can't be aggregated afterward. Expect a question on that trade-off.
Naming is tested directly: _total for counters, base units like _seconds and _bytes. Read the naming conventions once.
Alerting
Three things earned me points. An alert with for: 10m only fires if the condition holds for 10 continuous minutes. Recording rules pre-compute an expensive query into a new series. And who does what: Prometheus evaluates rules, Alertmanager groups, silences and routes, Grafana draws dashboards.
How I prepared
Three days of nothing but PromQL. Local Prometheus, node_exporter scraping my own laptop, real queries against real data. I kept going until I could predict the output before hitting enter. Nothing else came close.
Then the configuration docs and the alerting rules page, since the exam uses their exact field names. Then metric types and naming until they were automatic. For drilling functions away from a terminal, I made free PromQL flashcards.
Blog-post prep guides didn't help me much; most stay shallow and leave you stranded on PromQL. Paid courses exist, but I'd treat any of them as a supplement to writing queries yourself.
The order I'd use again:
- Prometheus and node_exporter locally. PromQL every day.
- Metric types and naming.
- Pull model, Pushgateway, service discovery, relabeling.
- Alerting rules, recording rules, Alertmanager vs Grafana.
- Practice questions to find what's still weak.
For step 5, I built a free PCA practice test. It's PromQL-heavy on purpose and covers metric types and alerting too, so you see your weak domains before exam day.
Thinking in label sets
At some point I stopped thinking "query the database" and started thinking "transform a set of labeled time series." Now I ask what an aggregation does to the labels before I ask about the numbers, and the questions stopped feeling random.
The PCA was part of my Golden Kubestronaut path, 15 of 15 CNCF certifications. The study material I collected is in awesome-kubestronaut.
I'm still not sure how much of my 82 came from production experience and how much from those three days of queries. My guess is the three days mattered more than I'd like to admit.
Originally published on yetmike.com
Top comments (0)