Executive Summary: One Cobalt live Secretary of State request can now produce an incomplete response with cachedData, later polling responses, and a callback or final retrieval. retryId connects those events to the provider process, but it does not guarantee that a lender's systems create only one review, one verification outcome, or one decision effect. The consumer needs its own logical request key, idempotency keys for side effects, and a state machine that permits exactly one terminal transition.
What Does retryId Control?
Which provider process does it identify?
Cobalt returns retryId when a search continues beyond the first request window. The identifier is used to check processing status and retrieve the result.[1] Cobalt's Help Center describes polling and callback paths for that open request.[2]
It is necessary correlation data. Store it exactly and associate every provider event with the same lender request.
Which business effects does it not control?
retryId does not know whether the lender already opened a review task, populated a screen, emitted a workflow message, marked verification final, or called a decision service. Those effects occur in customer systems with their own retries and failure modes.
Correlation tells the system which request an event belongs to. Idempotency tells it whether the event may have another effect.
Why Does cachedData Increase Duplicate Risk?
How many meaningful events can one request produce?
The first incomplete response may contain useful interim data. A polling worker may see the request again. A callback may deliver completion. A timed-out handler can repeat. Two workers can race. Each event is valid context for the same request, but none should create a new logical verification.
Cobalt documents 202 + Incomplete as continued processing rather than failure.[3] Repeating a request merely because the first response is incomplete can create an avoidable second process.
Which duplicate effects matter most?
Examples include two underwriter tasks, repeated customer notices, multiple evidence records presented as separate verifications, duplicate final-decision calls, or a second funding gate release. Even reversible interim work can create noise and inconsistent history when repeated.
Map effects, not just API calls:
• Interim display or prefill. At most one active version per observation.
• Review case. One open case per request and compared observations.
• Workflow message. One effect for one transition and purpose.
• Final verification event. One terminal transition per logical request.
• Decision invocation. One authorized call for the terminal version.
• Customer communication. One message for the named outcome.
Trace each effect through its destination. A queue may deduplicate messages while the worker still creates two database records, or a database may reject duplicates after two customer notifications have already been sent. The idempotency boundary must include the durable side effect that matters to the business, not merely the first service that receives the event.
Which Keys Should the Lender Own?
What is the logical request key?
It identifies one intended verification attempt in the lender's domain. It may combine an application-verification ID with an attempt number, but the exact design belongs to the lender. It should remain stable across the initial response, polls, callback, and final result.
Store retryId beneath that key as provider correlation. Do not let a network retry create a new logical request unless an authorized retry policy explicitly starts a new attempt.
What is an effect idempotency key?
It identifies one allowed business effect. Construct it from stable components such as logical request, transition, observation version, and purpose.
request_key = verification_1042_attempt_1
event_key = request_key + provider_event_identity
effect_key = request_key + transition + observation_version + purpose
terminal_key = request_key + final_verification
These are customer-owned examples, not Cobalt fields. Different effects need different keys because creating a review and completing verification are separate actions.
Store keys with their status and result. A reservation should move through states such as started, committed, or failed-retryable according to the lender's design. If a worker crashes, the next worker needs enough evidence to decide whether to continue, return a completed result, or escalate a conflict. A bare unique constraint can block duplicates but still leave an operation stranded.
How Should Events Enter the State Machine?
Which sequence should every handler follow?
Validate the payload, resolve the logical request, verify provider correlation, reserve or read the event key, inspect current state, evaluate the allowed transition, commit observation and state, enqueue permitted effects with unique keys, then acknowledge. A duplicate should return the stored outcome without repeating effects.
Microsoft's asynchronous request-reply pattern separates accepted work, status monitoring, and terminal result.[4] The lender state machine should preserve that lifecycle.
Which transitions should be impossible?
An interim event cannot mark final verification complete. A terminal request cannot move back to pending. Cache absence cannot become final no-match. A second terminal delivery cannot call the decision service again. A provider identifier cannot silently attach to another logical request.
Enforce these rules in a transaction or atomic compare-and-set. Interface checks alone do not protect background workers.
Keep observation storage and effect dispatch consistent with an outbox or equivalent pattern. Commit the new state and a uniquely keyed pending effect together, then let a dispatcher deliver it. If delivery repeats, the receiving service also checks the effect key. This closes the gap where state commits but a message is lost, or a message is sent before the state is durable.
How Should Interim cachedData Effects Be Deduplicated?
What if the same incomplete response is processed twice?
Persist one immutable observation for the same provider response identity or content version, then reuse its policy result. A repeated event may update delivery diagnostics but should not add a second review card or queue task.
Evaluate updatedAt and customer policy once per intended event context. Cobalt says cached timestamps support customer recency decisions,[5] but the timestamp is not itself an idempotency key.
What if a changed cached observation appears?
Store it as a new observation version only if the contract and response actually supply a materially new record. Re-evaluate named interim permissions and supersede the earlier visible version without deleting it. Use a new effect key tied to the version only for actions the policy allows again.
Do not assume that every repeated payload represents new data. Compare request identity, source, provider timestamps, stable identifiers, and retained bytes according to the lender's design.
Set explicit version precedence. A newer receipt time does not automatically mean a newer provider observation, and a changed title may reflect a different candidate rather than a record update. When the consumer cannot establish version order, preserve both and route the conflict to review instead of choosing the event that arrived last.
How Should Poll and Callback Races Be Controlled?
What if both paths deliver the final result?
Both should call one terminal transition under the same logical request and terminal_key. The first valid event commits the final observation and business effects. The second verifies consistency and returns the stored terminal outcome without repeating them.
Cobalt supports callback and polling paths for long-running requests.[2] Transport choice must not change the number of decisions.
What if a stale interim worker finishes after completion?
Reload the current request version before commit. If terminal state already exists, the worker may retain approved diagnostics but cannot write pending state or emit interim effects. Conditional updates or row version checks prevent backward movement.
AWS recommends idempotent retry handling so repeated operations have the same state effect as one.[6] Apply that principle to state and effects together.
Do not assume callback delivery is exactly once or ordered unless the actual provider contract says so. The Standard Webhooks specification discusses unique event identities and replay-safe consumers as general webhook design practices,[7] but it is not a statement that Cobalt implements every mechanism in that specification.
How Should Duplicate Protection Be Logged?
Which records explain the outcome?
Log logical request key, retryId, event identity, payload source, delivery path, prior state, proposed transition, deduplication outcome, effect keys, next state, and reason. OWASP recommends logs that include event status, reason, and action.[8]
Avoid full sensitive payloads in general logs. Point to controlled evidence records and apply lender retention and access policy.
How should a duplicate appear operationally?
Use a successful no-op or previously-processed result when the event is valid and already committed. Alert only when content conflicts, identity fails, or an illegal transition is attempted. Treating every harmless repeat as an error creates noise that hides true correlation problems.
Expose a compact support trace: first-seen time, repeat count, last-seen time, payload consistency result, state at receipt, and the stored effect outcome. This lets support confirm that a repeat was harmless without replaying a decision or inspecting sensitive payloads in a general log viewer.
NIST describes log management as a lifecycle across creation, storage, access, and disposal.[9] Retain deduplication evidence according to customer policy, not an assumed universal schedule.
How Should the Controls Be Tested?
Which concurrency tests are required?
Send the same incomplete event to two workers, repeat it after an interim effect, deliver poll and callback completion simultaneously, fail after reserving an event key, fail after committing state but before acknowledgment, deliver a stale interim event after final, and retry the terminal business call.
Assert state, observation count, review count, emitted messages, final-decision calls, and visible history. A database row that looks correct is not enough if the queue contains two effects.
Inject failure at every boundary: before key reservation, after reservation, after observation storage, after state commit, after queue publish, inside the effect consumer, and before acknowledgment. Then rerun the same event. The system should converge on the intended state and one effect, or surface a controlled exception with no ambiguous decision.
Which invariants prove the design?
One logical request maps to the intended provider process. One observation version creates at most one effect per purpose. Terminal state is monotonic. One terminal result creates at most one final business effect. Duplicate delivery is visible but harmless. Conflicting content enters review rather than overwriting.
Verify those invariants with production-like concurrency, not only serial unit tests. Use at least two workers, real transaction isolation, queue redelivery, and delayed callbacks. Keep the test trace as release evidence so later changes to storage or messaging can run the same contract.
After deployment, read back the first real traces across cache present, cache absent, and final completion. Confirm that stored keys, effect counts, and user-visible outcomes agree. Structural tests cannot prove that every production consumer honors the same idempotency boundary.
Cobalt's large-batch guidance recommends idempotent queues and controlled retries.[10] The retry and graceful-failure guide gives broader context, and the asynchronous webhook guide covers delivery structure. To review effect keys for your workflow, schedule a demo.
Assign one owner to review conflicts that safe deduplication cannot resolve automatically.












.png)