Certifications · PCA

PCA — the exam

The Prometheus Certified Associate (PCA) is the CNCF and Linux Foundation's associate-level, knowledge-based credential for the single most load-bearing tool in cloud native operations. Almost every platform this course touches scrapes metrics with Prometheus, stores them as labelled time series, queries them with PromQL, and pages a human through Alertmanager the moment something breaks — and PCA certifies you can do all four properly, not by pasting a query from a five-year-old blog post and hoping. It's an online, remote-proctored, multiple-choice exam: ninety minutes, no terminal, no live cluster. More than a quarter of the paper is PromQL alone, and it is unforgiving toward anyone whose Prometheus experience is entirely copy-paste. This page is the hub — the five official domains and weights straight from the CNCF curriculum, worked PromQL including the trap that catches almost everyone once, the four metric types, a recording rule paired with a symptom-based alert, and the logistics worth verifying before you register.

☺ Explain it like I'm 10

Imagine a nurse who walks the halls of a giant hospital every fifteen seconds and writes every patient's temperature on a notepad that never forgets anything. Later you can ask that notepad real questions — "whose temperature rose fastest in the last five minutes?" or "how many people ran a fever at 3am?" Prometheus is that nurse and that notepad, together. PromQL is the language you use to ask it questions, and it has its own grammar — ask it wrong and you get an answer that still looks like a number but means nothing. Alertmanager is the part that actually runs to fetch a doctor once an answer looks scary enough to matter. The PCA is the badge for knowing how to ask the notepad good questions, and — the harder skill — knowing exactly when an answer deserves to wake somebody up.

🐘Your host for this topic: Ellie the Elephant — she remembers everything, which is exactly the job a metrics store does. Ellie will show you where the numbers come from, how to ask them a good question in PromQL, and — the part most engineers get wrong — when a number actually deserves to page someone at 3am.

What the PCA actually tests

☺ Like you're 10: A test about one specific numbers-nurse, not about monitoring tools in general.

The PCA is a project-specific associate certification: an online, remote-proctored, multiple-choice knowledge exam covering Prometheus — its data model, its query language, how it scrapes, how it alerts, and where its limits are. It sits on this course's associate shelf alongside CGOA, CAPA, CBA, CCA, KCA and OTCA — all ninety minutes of pure multiple choice, unlike the hybrid ICA or the fully performance-based LFCS. There is no cluster to build and nothing to type against a clock: the exam certifies that you understand the data model, PromQL, the alerting pipeline and the shape of a metrics-instrumented service well enough to design and run one, not that you can install the Helm chart under pressure.

It suits platform and SRE engineers who own the monitoring stack and want the gaps in self-taught PromQL closed properly, developers instrumenting their own services who are asked to "add a metric" and would like to know which type actually fits, and anyone on call — the alerting domain is, quietly, a course in not destroying your own team with pages. It is not a substitute for the five core Kubernetes exams this course assumes are already cleared (see What Is Kubestronaut?), and it deliberately does not test Grafana panel-building, running Prometheus at real scale, or federation and long-term storage design — those are things an associate should know exist and why, not architect from scratch. The curriculum does list Understanding Prometheus Limitations as its own named competency, which is the exam politely telling you it will ask what Prometheus is bad at.

◆ Key idea

PCA is 28% a language exam. Treat PromQL like a small programming language you're learning, not a snippet library you're collecting. If you can explain — out loud, without hedging — why sum(rate(x[5m])) is correct and rate(sum(x)[5m]) is nonsense, you're most of the way through the hardest domain on the paper.

PromQL — worked, the way the exam asks it

☺ Like you're 10: The exam mostly hands you a question written in this language and asks what it actually returns.

PromQL has two core value types, and almost every question on the exam turns on telling them apart. An instant vector is one sample per series at one moment in time. A range vector — produced by adding a duration selector like [5m] — is every sample in a window, and it cannot be graphed or read directly; it has to pass through a function that collapses it back down to an instant vector, such as rate() or avg_over_time().

# SELECTING DATA — an instant vector, filtered by label matchers
# =  equals     !=  not-equals    =~  regex-match    !~  regex-not-match
http_requests_total{job="checkout", code=~"5.."}

# A RANGE VECTOR — every sample in the last 5 minutes, not graphable on its own
http_requests_total{job="checkout"}[5m]

# RATES AND DERIVATIVES — rate() gives the per-second average increase of a
# COUNTER and quietly handles counter resets for you. rate() FIRST, sum() SECOND:
sum by (code) (rate(http_requests_total{job="checkout"}[5m]))

# BINARY OPERATORS — matching series by their labels gives an error RATIO
  sum(rate(http_requests_total{job="checkout", code=~"5.."}[5m]))
/ sum(rate(http_requests_total{job="checkout"}[5m]))

# HISTOGRAMS — p99 latency in seconds. Keep the `le` label when aggregating!
histogram_quantile(0.99,
  sum by (le) (rate(http_request_duration_seconds_bucket{job="checkout"}[5m])))

# AGGREGATING OVER TIME — a range vector collapses to one value per series
min_over_time(node_memory_MemAvailable_bytes[1h])

# AGGREGATING OVER DIMENSIONS — collapse labels, keep only the ones you name
topk(5, sum by (pod) (rate(container_cpu_usage_seconds_total[5m])))

# TIMESTAMP METRICS — hours since the last successful backup completed
(time() - platform_backup_last_success_timestamp_seconds) / 3600

Four traps carry most of the marks on this domain. One: rate() and increase() take a range vector and only make sense on a counter — meaningless on a gauge, and running rate() over an already-summed series throws away the per-series reset handling that made it correct in the first place. Two: the range needs to span several scrape intervals, so rate(x[15s]) against a 15-second scrape interval returns nothing usable. Three: by keeps the labels you name and without drops them — and histogram_quantile specifically needs le kept, or it can't tell which bucket boundary any row belongs to. Four: a binary operation only matches series with identical label sets on both sides, which is why an otherwise-correct ratio silently returns empty when one side carries a label the other doesn't.

The five official domains and their weights

☺ Like you're 10: The test has five parts and they are not the same size — the biggest single part, by far, is the question language.

The names, percentages and competency lists below are transcribed from the CNCF's Prometheus Certified Associate (PCA) Exam Curriculum — not this course's interpretation of it. Five domains, 26 competencies, and the weights sum to exactly 100%; if a study guide elsewhere doesn't add up, it has been paraphrased somewhere along the way. Check the current version in the official CNCF curriculum repository before building a study plan around it:

🐘PromQL
28%
🦉Prometheus Fundamentals
20%
🐿️Observability Concepts
18%
🐢Alerting & Dashboarding
18%
🦫Instrumentation and Exporters
16%
DomainWeightCompetencies (official)
PromQL28%Selecting Data · Rates and Derivatives · Aggregating over time · Aggregating over dimensions · Binary operators · Histograms · Timestamp Metrics
Prometheus Fundamentals20%System Architecture · Configuration and Scraping · Understanding Prometheus Limitations · Data Model and Labels · Exposition Format
Observability Concepts18%Metrics · Understand logs and events · Tracing and Spans · Push vs Pull · Service Discovery · Basics of SLOs, SLAs, and SLIs
Alerting & Dashboarding18%Dashboarding basics · Configuring Alerting rules · Understand and Use Alertmanager · Alerting basics (when, what, and why)
Instrumentation and Exporters16%Client Libraries · Instrumentation · Exporters · Structuring and naming metrics

Read the shape rather than the list. PromQL plus Prometheus Fundamentals is 48%; add Instrumentation and Exporters and 64% of the exam is Prometheus proper. The remaining 36% splits between vendor-neutral observability theory and the alerting-and-dashboarding layer sitting on top of it — and that's where careless candidates lose marks, because Observability Concepts reaches well past metrics, into logs, events, tracing and spans and the SLO/SLA/SLI vocabulary. It reads like general knowledge, so it gets skipped, and it shouldn't be.

◆ Key idea

Two competencies are easy to under-read because they sound like filler, and aren't. Timestamp Metrics (in PromQL) is the time()-minus-a-timestamp pattern above — the backbone of freshness alerting and "how long since this batch job last succeeded?" questions. Understanding Prometheus Limitations (in Fundamentals) is a whole competency devoted to what Prometheus is not — not a clustered database, not built for long-term retention, not for per-request logging, not billing-grade. Both are cheap, guaranteed marks if you read them once on purpose.

The data model, exposition format and the four metric types

☺ Like you're 10: Every number Prometheus stores is really "a name plus some tags," and mixing up the wrong tag can flood the whole notepad.

Everything starts with the data model. A Prometheus time series is a metric name plus a set of labels, and every unique combination of label values is a separate series. That one sentence explains both Prometheus' power — slice along any dimension you recorded — and its most famous failure mode: put a user ID or a raw request path in a label, and you create millions of series, a cardinality explosion that eats memory and can take the whole server down. Targets expose their metrics over plain HTTP in the exposition format, a plain-text payload scraped on an interval.

# What a target actually serves at /metrics — the exposition format.
# HELP http_requests_total Total HTTP requests served.
# TYPE http_requests_total counter
http_requests_total{code="200",method="get"} 42981
http_requests_total{code="500",method="get"} 17

# A gauge can go up AND down.
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes 3.221225472e+09

# A histogram is really several series: cumulative _bucket, plus _sum and _count.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.1"}   41230
http_request_duration_seconds_bucket{le="0.5"}   42800
http_request_duration_seconds_bucket{le="+Inf"}  42998
http_request_duration_seconds_sum   3120.5
http_request_duration_seconds_count 42998
TypeBehaviourUse it forQuery it with
CounterOnly ever increases; resets to 0 on restartRequests served, errors, bytes sentrate(), increase() — never the raw value
GaugeGoes up and downMemory in use, queue depth, temperatureRead directly; avg_over_time(), delta()
HistogramCumulative buckets chosen in advance, plus sum and countRequest latency, response sizeshistogram_quantile() over rate(..._bucket[5m])
SummaryQuantiles calculated in the client, per instanceLatency when buckets can't be pre-chosenRead the quantile series — but it cannot be aggregated across instances

The histogram-versus-summary distinction is both a reliable exam question and a reliable production mistake: buckets are cumulative and aggregatable, so a fleet-wide p99 is computable, while client-side summary quantiles are not — averaging them across ten pods produces a number that looks precise and means nothing. Naming matters too: base units as a suffix (_seconds, _bytes), counters ending in _total, and a name that describes the thing measured rather than the dashboard panel you have in mind.

① Safe — two low-cardinality labels http_requests_total{method, code} method: get, post — code: 200, 500 get / 200 get / 500 post / 200 post / 500 = exactly 4 time series Every combination of label values is one distinct series — small and stable. ② Danger — add one bad label ...{method, code, user_id} user_id: thousands of distinct values = thousands of time series Cardinality explosion — memory pressure, slow queries, the TSDB can fall over.

Architecture, scraping and service discovery

☺ Like you're 10: Prometheus doesn't wait to be told things — it walks around and asks, on a timer, forever.

Prometheus is a single binary that pulls. On an interval it scrapes HTTP endpoints it has discovered, appends the samples to a local time-series database, evaluates recording and alerting rules, and forwards firing alerts to Alertmanager — a separate process responsible for grouping, silencing, inhibition and routing to receivers. The Pushgateway exists only for short-lived batch jobs that die before they can ever be scraped; it is a narrow exception, not a general push channel, and knowing that distinction is a classic push vs pull question.

global:
  scrape_interval: 15s        # how often we pull every target
  evaluation_interval: 15s    # how often rules are evaluated

scrape_configs:
  - job_name: kubernetes-pods
    kubernetes_sd_configs:            # SERVICE DISCOVERY: targets are not static
      - role: pod
    relabel_configs:                  # relabelling runs BEFORE the scrape
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep                  # drop every pod that isn't opted in
        regex: "true"
      - source_labels: [__meta_kubernetes_pod_label_app]
        target_label: app             # promote a pod label to a metric label

alerting:
  alertmanagers:
    - static_configs: [ { targets: ["alertmanager:9093"] } ]

rule_files:
  - /etc/prometheus/rules/*.yaml

Service discovery is why the pull model scales in Kubernetes: nothing has a stable IP, so Prometheus asks the API server what exists and continuously re-derives its target list rather than being told by hand. Relabelling is the filter sitting in front of that — keep and drop decide what gets scraped at all, while metric_relabel_configs runs after the scrape and is the emergency brake on a metric that turns out to be high-cardinality. And the limitations, stated plainly: Prometheus stores data locally and is not a clustered database; it is not built for long-term retention on its own — that's what Thanos, Mimir or Cortex are for; it is not for event-level or per-request logging; and it does not give billing-grade accuracy, because it samples on an interval rather than counting every event.

① Target exposes /metrics — exposition format ② Prometheus server scrapes on an interval, finds targets via service discovery ③ TSDB local time-series storage ④ Rule eval recording + alerting recording rules write back in ⑤ Alertmanager groups, routes, silences ⑥ Receiver — Slack / PagerDuty

Instrumentation, exporters, alerting and dashboards

☺ Like you're 10: How numbers get in, how a rule watches them, and how a bad number turns into a phone buzzing.

Metrics get in two ways. Client libraries — Go, Python, Java, Ruby, Rust and more — instrument your own code directly, choosing the metric type as you write the counter or the histogram. Exporters translate something that doesn't natively speak Prometheus into the exposition format: node_exporter for machines, blackbox_exporter for external probes, and one for practically every database in production.

from prometheus_client import Counter, Histogram, start_http_server

# Name in base units, counters end in _total, labels stay LOW cardinality.
REQUESTS = Counter(
    "http_requests_total", "Total HTTP requests served.",
    ["method", "code"],          # NEVER user_id, request_id or a raw URL path
)
LATENCY = Histogram(
    "http_request_duration_seconds", "Request duration in seconds.",
    buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],   # chosen up front, on purpose
)

@LATENCY.time()
def handle(request):
    response = do_work(request)
    REQUESTS.labels(method=request.method, code=response.status).inc()
    return response

start_http_server(8000)          # exposes /metrics for Prometheus to scrape

Alerting is where the exam turns opinionated, correctly. Rules come in two kinds: recording rules precompute an expensive expression on a schedule under a new name (conventionally level:metric:operation), and alerting rules fire once an expression keeps returning series for longer than for: allows.

groups:
  - name: checkout-slos
    rules:
      # RECORDING rule — precompute once, query it everywhere
      - record: job:http_request_errors:ratio_rate5m
        expr: |
          sum by (job) (rate(http_requests_total{code=~"5.."}[5m]))
            / sum by (job) (rate(http_requests_total[5m]))

      # ALERTING rule — a SYMPTOM, not a cause; `for` survives a blip
      - alert: CheckoutHighErrorRate
        expr: job:http_request_errors:ratio_rate5m{job="checkout"} > 0.05
        for: 10m
        labels:
          severity: page            # Alertmanager routes on labels
        annotations:
          summary: "Checkout is serving {{ $value | humanizePercentage }} errors"
          runbook_url: https://runbooks.example.com/checkout-high-error-rate

The when, what and why competency is the philosophy sitting behind that YAML. Alert on symptoms your users feel — error ratio, latency, saturation — not on causes like "CPU is at 80%," which may be entirely fine on its own. Every page has to be actionable and carry a runbook; anything not worth waking a human for is a ticket or a dashboard, never a page. In Alertmanager, grouping collapses a storm of related alerts into one notification, inhibition suppresses downstream alerts once a parent alert is already firing, and silences mute known, expected work. On the dashboard side: a panel is a PromQL query plus a visualisation, template variables let one dashboard serve many services, and the SLI/SLO/SLA vocabulary matters here too — an SLI is the measurement, an SLO is your internal target, an SLA is the contractual promise with consequences attached, and the error budget is the gap between the SLO and perfection.

🦆 Dot's-eye view

"Mission Control told me to 'add a metric for checkout latency.' I added a gauge, set it to the last request's duration, and built a panel on it. It looked beautiful and was completely useless — one slow request out of ten thousand vanished the instant the next one landed. After studying for the PCA I know that was a histogram the whole time, that the buckets need choosing on purpose, and that histogram_quantile exists specifically so a fleet-wide p99 doesn't lie to me. One lesson, and it's already paid for the study time twice over."

🐘 Ellie's memory drill · 30 min

Run Prometheus and one exporter locally — node_exporter is enough — and live in the expression browser, not a dashboard. Type these in order and predict each answer before you press enter: a bare counter; that counter wrapped in rate(...[5m]); the same summed by (instance); a gauge with avg_over_time(...[1h]); a two-vector division; a histogram_quantile that keeps le; and the same query with le dropped, so you see exactly how it breaks. Then open /targets and /service-discovery in the UI and read what relabelling actually did to your labels. One evening of that beats a week of reading about it.

How to prepare using this course

☺ Like you're 10: Most of what's on the test already has a page here — this is the shortcut through all of it.

Work the heaviest domain first, then drill. Continue with the PCA study plan for a week-by-week pacing schedule, then the practice question bank and two timed papers, Mock Exam · Set 1 and Mock Exam · Set 2. For the underlying concepts, read the Prometheus tool guide and The Prometheus Model; for dashboarding specifically, Grafana. If Kubernetes fundamentals still feel shaky — Prometheus in practice usually means a ServiceMonitor and a scrape config living inside a cluster — the Common Preparation section's Kubernetes Baseline You Need is the fastest patch. Before exam day, run the readiness checklist.

This course deliberately sequences PCA before OTCA: metrics and PromQL as a self-contained world first, so OTCA's broader Fundamentals of Observability domain — metrics, traces and logs together — has solid metrics vocabulary to build on rather than starting from zero. It's a soft on-ramp, not a hard prerequisite, so no harm is done sitting them in the other order. Together the two make you the person who owns the observability plane; see the certifications hub for how PCA and OTCA fit alongside this course's other seven exams. If you're weighing this against the platform-engineering angle, Platform Engineering's own PCA page covers the same curriculum from that course's perspective, and its Observability & Operations material is the performance-based complement to everything on this page — CNPE has you build the stack under a clock, where PCA only asks you to describe it correctly.

Exam logistics — and how to verify them

☺ Like you're 10: It's an online test you take from home with someone watching through your webcam. The price and length change, so always check the official page before you pay.

The PCA is administered by The Linux Foundation on behalf of the CNCF. Every figure below is a snapshot read from the official Linux Foundation and CNCF PCA pages — treat it as a starting point, not a guarantee:

ItemDetail (verify before booking)
FormatOnline, remote-proctored, multiple-choice — a knowledge exam. No live cluster, no terminal
Duration90 minutes
Question countNot published by either official page. Plan against the 90 minutes, not a number seen on a forum
Pass mark75% — published in the Linux Foundation's Multiple Choice Exam FAQ, which applies to every LF multiple-choice exam including this one
Validity2 years from the date you pass, matching the LF associate pattern
RetakeOne free retake typically included, alongside a 12-month eligibility window to schedule and sit the exam — confirm both are in the SKU you actually buy
PrerequisitesNone. PCA gates nothing and nothing gates it
PriceListed around US$250 for the exam alone at the time of writing, higher when bundled with a training subscription. Region, promotion and bundle all move this — treat it as a signpost, not a quote
Domains & weightsThe five above — 28 / 20 / 18 / 18 / 16, summing to 100%, across 26 competencies
⚠ Verify every number here before you pay

This is an independent, unofficial study resource, not affiliated with or endorsed by the CNCF or The Linux Foundation. Format, duration, pass mark, price, validity and even the curriculum version change without much notice, and third-party study pages — including this one — go stale between edits. The domains and weights above are transcribed from the official CNCF curriculum and sum to 100%; the row marked "not published" is deliberately left blank rather than filled with a plausible-sounding guess. Confirm every detail on the official Linux Foundation PCA page, the CNCF certification page, and the official curriculum repository before you register or pay for anything.

🎬 At Mission Control
🦊

Foxy: Why certify one specific tool? Isn't the whole point of cloud native being vendor-neutral?

🐘

Ellie: Because it isn't really one tool, Foxy — PromQL and the exposition format got borrowed by half the ecosystem. Learn this once and you can read Thanos, Mimir, Cortex, and most of what Grafana shows you.

🐿️

Nutty: And eighteen whole percent, Observability Concepts, reaches past metrics entirely — logs, events, traces, spans, SLOs versus SLAs. Free marks almost nobody revises on purpose!

👺

Gizmo: Easy fix. Alert on every metric we've got. Full coverage. Nothing gets past Gizmo. 🔔🔔🔔

🐢

Timmy: That's not coverage, that's a denial-of-service attack on your own on-call rotation. Alert on symptoms users actually feel. Everything else belongs on a dashboard, not in someone's pocket at 3am.

🦆

Dot: Can somebody explain why my p99 latency panel says four milliseconds when the page took six seconds to load?

🐘

Ellie: You dropped the le label when you aggregated, so histogram_quantile answered a question you never actually asked it. Twenty-eight percent of the exam, right there in one dropped label.

🐢 Timmy's checkpoint

1. Name the five official PCA domains and their weights. 2. Which domain is largest, and what percentage of the exam is Prometheus proper once Instrumentation and Exporters is added in? 3. Why is sum(rate(x[5m])) correct while rate(sum(x)[5m]) is wrong? 4. What's the difference between a histogram and a summary, and why does it matter when you aggregate across instances? 5. What does the for: field on an alerting rule actually do? 6. What is Pushgateway actually for, and what is it not for? 7. Which exam details should you never trust from a third-party page, and where do you check them instead?

Check your answers
  1. PromQL 28%; Prometheus Fundamentals 20%; Observability Concepts 18%; Alerting & Dashboarding 18%; Instrumentation and Exporters 16%.
  2. PromQL at 28%. PromQL (28) + Fundamentals (20) + Instrumentation and Exporters (16) = 64% of the exam is Prometheus itself.
  3. rate() has to run on a counter range vector so it can handle each series' own resets correctly; summing first destroys the individual series, and their resets along with it. Rate first, then aggregate.
  4. A histogram exposes cumulative _bucket series with pre-chosen boundaries, so buckets can be summed across instances and a fleet-wide quantile computed with histogram_quantile(). A summary computes its quantiles in the client, per instance — those quantiles cannot be aggregated; averaging them across pods produces a meaningless number.
  5. for: requires the expression to keep returning that series continuously for the given duration before the alert moves from pending to firing — it suppresses transient blips from ever paging anyone.
  6. Short-lived batch jobs that finish and disappear before Prometheus can scrape them. It is not a general push endpoint — Prometheus itself is a pull system, and Pushgateway is a narrow, deliberate exception.
  7. Duration, question count, pass mark, price, retake policy, eligibility window and validity — and confirm the domain weights too. Check the official Linux Foundation PCA page and the CNCF certification page — they change, and they're the only authority.