Software Engineering Foundations

Software Engineering Foundations is 7.4% of the CCDV-F blueprint, about four of the 53 scored questions and the second-largest sub-skill on the paper. It tests ordinary engineering discipline applied to a slow, metered, non-deterministic dependency: timeouts that compose with retries, idempotent side effects, bounded concurrency, and code you can test without a live model.

Written by Kiran Manne

7.4% of the CCDV-F blueprint, which is roughly 4 questions of 53. It sits inside Applications and Integration, worth 33.1% in total.

Software Engineering Foundations is the second-largest sub-skill on the paper at 7.4 percent, about four of the 53 scored questions. Almost none of it is Claude-specific, which is why candidates skim it and why it repays attention: the questions are set by people who have watched competent engineers make the same handful of mistakes once a model became a dependency.

The mental model to carry in is that a model call is a network call with unusual properties. It is slow, measured in seconds rather than milliseconds. It is metered, so your concurrency is capped by a quota rather than by your own capacity. It is non-deterministic, so identical input can produce different output. And it is expensive, so a wasted call carries a price rather than merely a delay.

Every practice examined here follows from one of those four properties. Slow means timeouts and cancellation matter. Metered means queueing and backpressure matter. Non-deterministic means your seams and test doubles matter. Expensive means retries need a policy rather than a reflex. Read a scenario, work out which property is biting, and the intended answer is usually the standard remedy for that property.

What the exam tests here

  • How a client timeout and an automatic retry policy multiply into a real worst-case wall-clock time
  • Making side effects triggered by model output safe to happen twice
  • Applying backpressure when concurrency is bounded by a quota rather than by your own capacity
  • Isolating a slow dependency so its saturation does not take the rest of the service down with it
  • Designing seams that let the calling code be tested without a live model
  • Structured logging and correlation across the steps of a single run

Timeouts and retries multiply

Client libraries ship with both a request timeout and an automatic retry count, and engineers configure them separately without noticing they compose. A ten-minute timeout with two automatic retries is a thirty-minute worst case inside one call, which will outlast the gateway in front of it and any user's patience.

Two details are worth carrying. The units differ between language SDKs, with some taking seconds and at least one taking milliseconds, so a value copied between codebases can be wrong by a factor of a thousand. And a per-request override is normally available, which is the right tool when one route is interactive and another is a long generation. Decide the budget for the whole operation first, then divide it.

Idempotency, because reruns are normal here

Anything a model-driven flow can cause to happen twice must be safe happening twice. Retries, resumed sessions, a user pressing a button again and an agent re-issuing a call it believes failed all produce duplicates, and none of those are exotic.

The remedy is ordinary: derive a stable key for the effect from the work rather than from the attempt, record it before performing the side effect, and check it on the way in. The subtlety specific to this setting is that the key must not come from the model's output, which can legitimately differ between attempts at the same task. Key on the request that started the work, and treat a matching key as a completed effect rather than a conflict.

Bound the concurrency you can actually sustain

A service fanning out model calls discovers its quota long before it discovers its CPU. When demand exceeds what the quota allows, the unbounded failure mode is the worst one: everything slows together, retries stack on top of the queue, and the service degrades as a whole.

Put an explicit limit in front of the dependency (a semaphore, a worker pool, a queue with bounded depth) and decide what happens when the limit is reached. Shedding load with a clear error beats accepting work you cannot do. Add isolation while you are there, so a saturated model path cannot exhaust the threads or connections the rest of the service needs to answer a health check.

Seams: test the code without calling the model

A codebase calling the client library directly from its business logic can only be tested by spending money and tolerating variance. Put an interface between them.

The logic assembling prompts, validating output, classifying errors and applying business rules is deterministic and deserves ordinary unit tests against recorded responses, including the awkward ones: a truncated answer, a decline, a malformed payload, a result marked as failed. Reserve live calls for a small set of contract tests confirming the request still validates and the response still has the expected shape.

This is not purity for its own sake. It is the difference between a suite that runs in seconds on every commit and one nobody runs.

Where candidates go wrong

Trap: retrying an action that has already taken effect

A call times out, the client retries, and the work had in fact completed the first time, so the effect happens twice. With a model in the loop the effect is often visible: a message sent, a ticket opened, a payment initiated.

The instinct to fix this by lengthening the timeout treats the symptom, because the network can fail after the work and before the response at any duration. The fix is making the effect idempotent, keyed on the originating request, so a duplicate attempt is recognised and discarded. Options reaching for a longer timeout instead are the distractor.

Trap: logging the response and calling it observability

Dumping the full response body into the log costs storage, frequently captures content that should not be retained, and still fails to answer the questions an incident asks.

What you need is dimensional: which model identifier ran, how the turn ended, the token counts, the elapsed time, the identifier that ties the call to a support conversation, and a correlation identifier tying every step of a multi-step run together. Record those as fields rather than prose, and keep content logging deliberate and scoped. A scenario describing an incident nobody can reconstruct is usually pointing here.

Trap: treating the model as an ordinary fast dependency

Patterns tuned for a database call transplant badly. A connection pool sized for millisecond work is exhausted by calls taking twenty seconds. A synchronous request-and-wait path with no streaming leaves a user staring at nothing for the duration. A health check that issues a real completion turns monitoring into a cost line.

The engineering answer is to size, isolate and instrument the dependency for what it is: slow, quota-bound and billed. Options applying an unmodified conventional pattern without acknowledging that profile are usually the ones to reject.

Common questions

How much of the CCDV-F exam is Software Engineering Foundations?

7.4 percent, which is about four of the 53 scored questions and the second-largest sub-skill on the blueprint. It sits inside Applications and Integration, whose six sub-skills together account for a third of the paper.

Is this section really about Claude at all?

Mostly not, and that is deliberate. The certification targets engineers shipping production systems, so it examines whether the ordinary disciplines survive contact with a dependency that is slow, metered, non-deterministic and billed per call. The Claude-specific part is the properties, not the practices.

How do I test code that calls a model?

Separate the deterministic parts and test those properly. Prompt assembly, output validation, error classification and business rules can all be exercised against recorded responses, including truncated, declined and malformed ones. Keep a thin layer of live contract tests to confirm the request still validates and the response shape still holds, and run those far less often.

What should be logged for every model call?

Fields rather than prose: the model identifier actually used, how the turn ended, the token counts, the elapsed time, the request identifier the provider returned, and a correlation identifier shared by every step of the same run. That set answers most incident questions without retaining response content you may not be permitted to keep.

The rest of Applications and Integration

Practise this

The CCDV-F bank covers every sub-skill in the blueprint, weighted the way the real paper is. Free sample questions need no account.

Free CCDV-F questions