Skip to content

API version 20240415 removed race-free flag enumeration: offset pagination can skip/duplicate flags under concurrent archival #134

Description

@keeely

Regression

Before 20240415, GET /api/v2/flags/{projectKey} returned the full set in a
single atomic response — a race-free enumeration. 20240415 switched it to
offset pagination (limit/offset, default 20) with no race-free
alternative
.

LD-API-Version GET /flags behaviour
20191212, 20210729, 20220603 Full set in one response, no _links.next — atomic snapshot
20240415 (current) Paginated, limit=20 default, _links.next present — not race-free

_links.next is not a cursor. Its href is just …&limit=20&offset=20
offset pagination re-encoded as a link, so following it is identical to
incrementing offset and inherits the same race. A real cursor would carry an
opaque, position-stable token ("resume after key X"), not a numeric offset.
Quick test: if next.href contains offset=, it's position-based and races.

Offset pagination isn't a consistent enumeration: archiving a flag mid-walk
removes it from the archived:false set, shifting all later offsets down by one,
so a flag present for the entire walk can be skipped (unarchive → duplicate).
The unpaged behaviour now only survives on the deprecated versions above, so
once those are enforced, no supported version offers race-free enumeration at all.

Reproduction

# pre-20240415: one atomic page, no next link
curl -s -H "Authorization: $LD_TOKEN" -H "LD-API-Version: 20220603" \
  ".../flags/$PROJECT?filter=archived:false" \
  | jq '{count:(.items|length), hasNext:(._links|has("next")), total:.totalCount}'
# count == totalCount, hasNext == false

# 20240415: paginated, and next.href is offset-based
curl -s -H "Authorization: $LD_TOKEN" -H "LD-API-Version: 20240415" \
  ".../flags/$PROJECT?filter=archived:false" \
  | jq '{count:(.items|length), next:._links.next.href, total:.totalCount}'
# count == 20, next ends in "&offset=20"

Skip race on 20240415: page through ?filter=archived:false; archive any flag
behind the current offset; subsequent offsets shift down and the flag at the next
page boundary is never returned.

Request

Restore race-free complete enumeration on a supported version. Not asking to
revert to unpaged — cursor/keyset pagination keeps the paging model while
being immune to offset shift. (For dotted keys, an S3-style prefix+delimiter
listing would also give bounded, atomic per-subtree pages.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions