Description
Trusted Server saves IDs from the ts-eids and sharedId cookies while finishing every returning-user response. A normal publisher page creates many first-party requests at once, including scripts, integration requests, analytics calls, and auctions. Each response may try to update the same EC record in KV.
A matched production browser run recorded 45 warnings for one EC identity:
CAS conflict after 5 retries upserting 3 partner IDs
The page continued because this sync is best-effort, but some partner IDs may not have been saved.
Relevant code:
crates/trusted-server-core/src/ec/finalize.rs
crates/trusted-server-core/src/ec/prebid_eids.rs
crates/trusted-server-core/src/ec/kv.rs
crates/trusted-server-adapter-fastly/src/app.rs
crates/trusted-server-adapter-fastly/src/main.rs
Current behavior
For every returning-user response:
- Read partner IDs from the request cookies.
- Read the EC record and its generation number from KV.
- Merge the partner IDs.
- Write only if the generation number has not changed.
- Retry immediately up to five times when another request writes first.
Requests may contain cookies captured at different points during the page load. They can also finish in a different order from the one in which they started.
CAS prevents two requests from writing the same version of the record. It does not tell Trusted Server which request has the newest cookie values. An older request can reread the record and try to replace a newer partner ID with an older value.
Impact
- Some partner IDs may not be saved.
- Older cookie values may replace newer values.
- Page loads create unnecessary KV reads and writes.
- Immediate retries use edge compute while the record remains busy.
- Repeated warnings make Fastly logs harder to read.
- Later auctions and partner syncs may use an incomplete identity record.
The browser request still succeeds, so this problem is easy to miss without Fastly logs.
Proposed solution
Limit where partner IDs are saved
Keep consent checks, withdrawal handling, and EC cookie handling on every response where they are currently required. Limit only the partner ID sync.
Save EID cookie values during:
- New EC creation
- Top-level document navigation
POST /auction
Do not save them while serving static assets, integration requests, analytics calls, or other page resources.
If navigation and auction requests miss IDs discovered late in the page load, add a dedicated browser sync endpoint instead of saving IDs on every response.
Replace repeated writes with one conflict check
Replace the five immediate write retries with:
- Read the record and attempt one conditional write.
- If another request writes first, read the record one more time.
- Return success if the desired IDs are already present.
- Otherwise defer the update to a later navigation or auction request.
Do not make another immediate write from the same request after the conflict.
Prevent older values from replacing newer ones
Before allowing one partner ID value to replace another, define a clear rule for deciding which value is newer. This may require storing the time when Trusted Server observed each partner ID.
Until that rule exists, a request that loses a CAS conflict should not overwrite a different value found during the follow-up read.
Add measurements
Add counters for:
- Partner ID sync attempts
- Requests where the values already matched
- Successful KV writes
- Conflicts where another request had already saved the same values
- Updates deferred after a conflict
- Whether the sync came from navigation, auction, or new EC creation
Logs and measurements must not contain EC IDs or partner ID values.
Completion criteria
- Static files and integration requests do not write partner IDs to KV.
- New EC creation, document navigation, and
/auction still save partner IDs.
- A conflict returns success when another request already saved the same values.
- An older request cannot replace a newer partner ID after losing a conflict.
- Consent withdrawal continues to take priority on every applicable route.
- Concurrent request tests no longer exhaust five immediate retries.
- Measurements distinguish successful, duplicate, and deferred updates without exposing identity data.
Out of scope
- Increasing the retry limit
- Sleeping inside an edge request
- Logging EC IDs or partner ID values
- Changing consent withdrawal behavior
Description
Trusted Server saves IDs from the
ts-eidsandsharedIdcookies while finishing every returning-user response. A normal publisher page creates many first-party requests at once, including scripts, integration requests, analytics calls, and auctions. Each response may try to update the same EC record in KV.A matched production browser run recorded 45 warnings for one EC identity:
The page continued because this sync is best-effort, but some partner IDs may not have been saved.
Relevant code:
crates/trusted-server-core/src/ec/finalize.rscrates/trusted-server-core/src/ec/prebid_eids.rscrates/trusted-server-core/src/ec/kv.rscrates/trusted-server-adapter-fastly/src/app.rscrates/trusted-server-adapter-fastly/src/main.rsCurrent behavior
For every returning-user response:
Requests may contain cookies captured at different points during the page load. They can also finish in a different order from the one in which they started.
CAS prevents two requests from writing the same version of the record. It does not tell Trusted Server which request has the newest cookie values. An older request can reread the record and try to replace a newer partner ID with an older value.
Impact
The browser request still succeeds, so this problem is easy to miss without Fastly logs.
Proposed solution
Limit where partner IDs are saved
Keep consent checks, withdrawal handling, and EC cookie handling on every response where they are currently required. Limit only the partner ID sync.
Save EID cookie values during:
POST /auctionDo not save them while serving static assets, integration requests, analytics calls, or other page resources.
If navigation and auction requests miss IDs discovered late in the page load, add a dedicated browser sync endpoint instead of saving IDs on every response.
Replace repeated writes with one conflict check
Replace the five immediate write retries with:
Do not make another immediate write from the same request after the conflict.
Prevent older values from replacing newer ones
Before allowing one partner ID value to replace another, define a clear rule for deciding which value is newer. This may require storing the time when Trusted Server observed each partner ID.
Until that rule exists, a request that loses a CAS conflict should not overwrite a different value found during the follow-up read.
Add measurements
Add counters for:
Logs and measurements must not contain EC IDs or partner ID values.
Completion criteria
/auctionstill save partner IDs.Out of scope