OTCA — the exam
The OpenTelemetry Certified Associate (OTCA) is the CNCF and Linux Foundation's associate-level, knowledge-based credential for the specification that has quietly become the shared plumbing under almost every modern observability stack — not a dashboard, not a database, but the one data model, one wire protocol and one Collector that receives, reshapes and routes telemetry no matter which backend it lands in. It's an online, remote-proctored, multiple-choice exam: ninety minutes, no terminal, no live cluster. Nearly half the paper (46%) is the OpenTelemetry API and SDK — the code that produces telemetry — and another quarter (26%) is the Collector, the infrastructure that carries it, which means 72% of this exam is two pieces of real software, not abstract "three pillars" theory. This page is the hub: the four official domains and their weights, a worked SDK pipeline, a Collector config wired end to end, and the trap that catches almost every first-time candidate once.
Imagine every module on a space station — life support, propulsion, the science bay — kept its own logbook, but each one used different units and a different word for "trouble." Mission Control couldn't tell whether a spike in one log meant the same thing as a spike in another. OpenTelemetry is every module agreeing on one logbook format, one unit system, and one word for "trouble" — plus a relay satellite (the Collector) that receives every module's readings, tidies them up, and beams them down to whichever ground station is watching. The OTCA is the badge saying you can both write in that shared logbook and operate the relay satellite in the middle.
What the OTCA actually tests
☺ Like you're 10: A test about the one project that ships almost all the data everything else draws pictures with — not a general knowledge quiz about observability.
The OTCA is a project-specific associate certification: an online, remote-proctored, multiple-choice knowledge exam covering OpenTelemetry — the API and SDK applications instrument against, and the Collector that receives, reshapes and exports that telemetry. It sits on this course's associate shelf alongside CGOA, CAPA, CBA, CCA, KCA and PCA — 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 the clock; the exam certifies that you understand the data model, the API/SDK split, the Collector's configuration surface and the common failure modes of a telemetry pipeline well enough to design and run one.
It suits platform and observability engineers who run a Collector fleet and want the specification behind the YAML they already maintain, SREs who live in traces and metrics during an incident and are tired of guessing why a trace stops dead at a service boundary, and application developers instrumenting their own services — the 46% API-and-SDK domain is close to their working day already. It is not a substitute for the five core Kubernetes exams this course assumes are already cleared (see What Is Kubestronaut?), and it is not general "three pillars of observability" trivia — it examines one specification and its reference implementations in genuine depth.
OTCA tests a specification and its reference implementations, not a vendor product. The data model, semantic conventions, OTLP and the SDK pipeline are the spine of the exam; backends such as Jaeger, Prometheus and Grafana only appear as places the data lands. Study your dashboards and skip the spec, and you'll ace the smallest domain on the paper while struggling with the other three-quarters.
The four official domains and their weights
☺ Like you're 10: Four chunks, wildly uneven — almost half the test is one of them, and the other three split what's left.
The official OpenTelemetry Certified Associate (OTCA) curriculum, published by the CNCF, splits the exam into four weighted domains covering twenty competencies in total. The bars below are that blueprint, drawn to scale, and the four weights sum to exactly 100% (46 + 26 + 18 + 10):
| Domain | Weight | Competencies |
|---|---|---|
| The OpenTelemetry API and SDK | 46% | Data Model · Composability and Extension · Configuration · Signals (Tracing, Metric, Log) · SDK Pipelines · Context Propagation · Agents |
| The OpenTelemetry Collector | 26% | Configuration · Deployment · Scaling · Pipelines · Transforming Data |
| Fundamentals of Observability | 18% | Telemetry Data · Semantic Conventions · Instrumentation · Analysis and Outcomes |
| Maintaining and Debugging Observability Pipelines | 10% | Context Propagation · Debugging Pipelines · Error Handling · Schema Management |
72% of the paper is two pieces of software — the SDK you configure inside an application, and the Collector you run as infrastructure — so a revision plan built on reading about observability in the abstract has only prepared for 18% of the exam. Notice too that Context Propagation is the only competency named twice, in both the 46% and the 10% domains: the curriculum is telling you where candidates actually fail. A trace that snaps in half at a service boundary is the signature failure of a distributed pipeline, and you're expected to know both the mechanism and how to debug it.
The SDK pipeline: provider, sampler, processor, exporter
☺ Like you're 10: The API is a form you fill in. Nothing happens with that form until an SDK actually picks it up, reads it, and mails it somewhere.
This is the single highest-yield idea on the whole exam. The API is what instrumentation calls — libraries depend on it, and by design it is a no-op until something registers a real implementation. The SDK is that implementation: a pipeline of a provider, a sampler, one or more processors, and an exporter, all hung off a resource that says which service produced the data. Register nothing, and every span your code creates is thrown away at the moment it's created — no error, no telemetry, silence. Here's a trace pipeline wired by hand, read as a diagram rather than code to memorize:
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.sampling import ParentBased, TraceIdRatioBased
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.composite import CompositePropagator
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
from opentelemetry.baggage.propagation import W3CBaggagePropagator
resource = Resource.create({
"service.name": "docking-control",
"service.version": "1.4.3",
})
exporter = OTLPSpanExporter(endpoint="otel-collector.observability:4317") # gRPC, port 4317
provider = TracerProvider(
resource=resource,
sampler=ParentBased(TraceIdRatioBased(0.1)), # honour the parent, else sample 10%
)
provider.add_span_processor(BatchSpanProcessor(exporter)) # buffer and export in batches
trace.set_tracer_provider(provider) # register the SDK behind the global API
set_global_textmap(CompositePropagator([
TraceContextTextMapPropagator(), W3CBaggagePropagator(),
]))
tracer = trace.get_tracer("docking-control.approach")
with tracer.start_as_current_span("compute-burn") as span:
span.set_attribute("burn.delta_v_mps", 4.2)
# ... the actual work happens here ...
# providers buffer in memory — an unflushed process exit silently drops the last batch
provider.shutdown()Four things there are exam material on their own. The sampler — parent-based respects whatever decision an upstream service already made, so a trace is sampled consistently end to end; applying a ratio sampler independently in every service shreds traces into fragments. Batch vs. simple processor — batching is production behaviour, the simple processor exports one span at a time and exists mainly for debugging. Shutdown — a process that exits without flushing loses whatever the batch processor was still holding. And the resource, which is where the exam's schema-management competency starts: it carries the identity the Collector and every backend will key on.
Endpoint and protocol are two separate settings that must agree. gRPC listens on 4317, HTTP on 4318, and the HTTP exporter appends a signal-specific path such as /v1/traces on its own. Point an HTTP exporter at the gRPC port, or vice versa, and the failure is silent from the application's point of view — the SDK's queue just quietly fills and drops. Expect at least one question built on exactly this mismatch.
The Collector: five component types, and the wiring trap
☺ Like you're 10: The relay satellite has five kinds of parts. Bolt one on but forget to plug it into the actual signal path, and it just sits there doing nothing — forever, with no warning light.
The Collector is one binary that receives telemetry, reshapes it and sends it on. It has exactly five component types, and knowing them cold is most of the 26%: receivers get data in (otlp, prometheus, filelog, hostmetrics), processors change data in flight, in the order you list them (memory_limiter, batch, transform, tail_sampling), exporters send it out (otlp, otlphttp, prometheusremotewrite, debug), extensions add capabilities outside any data path (health_check, zpages), and connectors join two pipelines, acting as the exporter of one and the receiver of the next (spanmetrics, routing). Pipelines are per-signal — traces, metrics, logs — and live under service.pipelines.
The rule that catches almost every first-time candidate: a component that is defined under receivers, processors or exporters but never listed inside a pipeline simply does not run. No startup error, no warning in the logs, no metric — the config parses cleanly and the Collector starts fine. It just quietly never touches a single record. Watch it happen in the config below: transform is fully configured, syntactically correct, and dead on arrival.
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
processors:
memory_limiter: # FIRST in every pipeline -- sheds load before the heap dies
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
batch: # LAST -- batching after filtering wastes less work
timeout: 5s
send_batch_size: 8192
transform: # OTTL -- meant to redact a header before export
trace_statements:
- context: span
statements:
- delete_key(attributes, "http.request.header.authorization")
exporters:
otlp/backend:
endpoint: tempo-distributor.observability:4317
sending_queue: { enabled: true, queue_size: 5000 }
retry_on_failure: { enabled: true, initial_interval: 5s, max_elapsed_time: 300s }
debug:
verbosity: detailed # print telemetry to the Collector's own log -- debugging only
extensions: [health_check, zpages]
service:
extensions: [health_check, zpages]
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch] # <- "transform" is defined above but not listed here
exporters: [otlp/backend, debug]
telemetry:
metrics: { level: detailed } # the Collector's own metrics -- your first debugging toolThe transform processor above is valid YAML sitting right next to batch and memory_limiter — but the traces pipeline's processors list only names two of the three. Nothing calls transform, so the authorization header it was meant to strip keeps riding downstream, unredacted, indefinitely. This is the single most common Collector misconfiguration in production and a near-certain exam scenario: given a config, you'll be asked which processor actually runs, and the answer is "only the ones the pipeline lists," full stop — definition and wiring are two separate steps.
Context propagation, and the smallest domain
☺ Like you're 10: Every message a station module sends carries a tiny stamped card so the next module knows which mission log it belongs to. Lose the card, and you start a brand new log by accident.
Inside a process, OpenTelemetry carries a Context holding the active span and any baggage. Across a network hop, a propagator serializes that context into headers and the receiver deserializes it. The default is W3C Trace Context — a traceparent header carrying version, trace ID, span ID and a sampled flag, plus an optional tracestate for vendor-specific data and a separate baggage header for user-defined key/value context that is not automatically copied onto spans and should never carry secrets, since it rides in plaintext to every downstream hop. A trace breaks when a service fails to extract an incoming context (it silently starts a fresh trace), when neighbouring services run different propagators, or across an async boundary — a queue, a background job — where context isn't explicitly carried forward.
The remaining 18% — Fundamentals of Observability — is the smallest substantial domain and the most conceptual: the Resource/InstrumentationScope/record shape every signal shares, semantic conventions (agreed names like service.name and http.request.method that make a dashboard work against any conformant service), what counts as good instrumentation, and reading outcomes such as golden signals and SLOs out of the data you now have. It's genuinely the easiest domain to under-revise, because it feels like "the stuff you already know."
"I added the SDK to my service, saw nothing land in Grafana, and filed a ticket blaming the platform team. Turns out my exporter was pointing at port 4317 with the HTTP protocol set — the gRPC port, an HTTP client. Once I understood that the API does nothing until an SDK is registered, and that the endpoint and the protocol are two separate settings that must agree, most of my 'platform bugs' turned out to be mine."
How to prepare using this course
☺ Like you're 10: Most of this test already has a page here. Read them in weight order and you've read the syllabus.
Work the heaviest domain first, then drill. Continue with the OTCA 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 OpenTelemetry Data Model and the OpenTelemetry Collector tool guide; for the metrics vocabulary that makes the Fundamentals domain easier, PCA is the recommended on-ramp — see The Order of Attack for why this course sequences PCA first. Before exam day, run the readiness checklist.
The Collector is usually deployed on Kubernetes as a DaemonSet or Deployment, and the OpenTelemetry Operator injects zero-code agents from an Instrumentation custom resource — so a working baseline of Kubernetes objects and controllers helps here too; see The Kubernetes Baseline You Need if any of that feels shaky. This course covers OTCA and PCA as the observability pair on this shelf; the sibling Platform Engineering course goes further with OpenTelemetry as one tool among many feeding its CNPE Observability & Operations domain, and its own OpenTelemetry deep-dive is a good second read once the fundamentals here are solid.
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. Prices and timings change, so always check the official page before you pay.
The OTCA is administered by The Linux Foundation on behalf of the CNCF. Every figure below is a snapshot — treat it as a starting point, not a guarantee:
| Item | Detail (verify before booking) |
|---|---|
| Format | Online, remote-proctored, multiple-choice. No cluster, no terminal, no performance tasks |
| Duration | 90 minutes |
| Question count | Not published by the official pages. Plan against the 90 minutes, not against a number you saw on a forum |
| Pass mark | 75% — published in the Linux Foundation's Multiple Choice Exam FAQ, which applies to every LF multiple-choice exam including this one, even though it isn't restated on the OTCA product page itself |
| Level | Associate — alongside KCA, PCA, CGOA, CAPA and CBA on this shelf |
| Prerequisites | None. No prior certification is required, and OTCA is not required for anything else |
| Retake & validity | Historically one free retake within a roughly 12-month eligibility window, with the credential valid for around 2 years — confirm both against the SKU you actually buy |
| Price | Listed around US$250 for the exam alone at the time of writing, and discounted often enough that the sticker price is rarely what people pay |
| Domains & weights | The four above — 46 / 26 / 18 / 10, summing to 100%, across 20 competencies |
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 rows marked "not published" are left blank rather than filled with a plausible guess. Confirm every detail on the official Linux Foundation OTCA page and the CNCF certification page before you register or pay for anything.
Foxy: I bolted the SDK onto docking-control an hour ago. Grafana still shows nothing. Is OpenTelemetry just broken?
Ellie: Did you actually register a TracerProvider, or just import the API and call it a day? The API is a no-op by design — nothing exists until an SDK is behind it.
Foxy: ...I imported the API and called it a day.
Gizmo: Or skip the memory_limiter processor entirely — one less YAML block, and who's counting bytes anyway? 😈
Timmy: Skip that one and a slow backend backs the whole Collector up until it gets OOMKilled. It's listed first in every real pipeline for a reason — it's the guardrail that keeps the guardrails running.
Nutty: Found the actual bug in the Collector config, by the way — transform is sitting right there under processors, fully valid, and nobody added it to the pipeline's list. The auth header it's supposed to strip has been leaking for two weeks.
Ellie: Defined and wired are two different steps. The exam asks that exact question more than once — write it on your hand.
1. Name the four OTCA domains and their weights, and say which two together make up 72% of the paper. 2. What is the difference between the OpenTelemetry API and the SDK, and what happens if you instrument code but never register an SDK? 3. Name all five Collector component types. 4. A processor is fully defined under processors in a Collector config — what else must be true before it ever touches a single record? 5. What does a traceparent header carry, and name two distinct ways a trace can break at a service boundary. 6. Why is OTEL_EXPORTER_OTLP_ENDPOINT paired with a protocol setting, and what happens when the two disagree? 7. Which exam details should you never trust from a third-party page — including this one?
Check your answers
- The OpenTelemetry API and SDK 46%; The OpenTelemetry Collector 26%; Fundamentals of Observability 18%; Maintaining and Debugging Observability Pipelines 10%. The API/SDK and the Collector together are 72% of the paper.
- The API is the interface instrumentation calls and is a no-op by default; the SDK is the implementation you register at start-up, holding the provider, sampler, processor(s) and exporter. Instrument without registering an SDK and every span is discarded at creation — no telemetry is produced, and no error is raised.
- Receivers, processors, exporters, extensions and connectors.
- It must be listed inside a pipeline under
service.pipelines(for the relevant signal). A component defined but not referenced there parses fine and simply never runs — no warning, no log line. traceparentcarries version, trace ID, span ID and trace flags (including the sampled bit). A trace breaks when a service fails to extract the incoming context (starting a fresh trace), when neighbouring services use different propagators, or across an async boundary where context isn't explicitly carried forward.- gRPC and HTTP listen on different ports (
4317vs4318), and the HTTP exporter appends a signal-specific path on its own. A mismatched endpoint/protocol pair fails silently — the SDK's queue fills and drops with no error visible to the application. - Duration, question count, pass mark, price, retake policy, eligibility window and validity — and, over a long enough period, the domain weights themselves. Confirm them on the official Linux Foundation OTCA page before registering — it is the only authority.