The problem

getLocationMapPoints had significantly worse p99 than getLocations under identical load in charge-points v0.3 load tests. Same endpoint family, assumed same defaults — but not the same behaviour.

Investigation checklist

  1. Verify data parity — paginate both endpoints and count unique UIDs before blaming query performance.
offset=0
while true; do
  uids=$(curl -s -H "x-api-key: $KEY" "$URL?offset=$offset" | jq -r '.items[].uid // empty')
  count=$(echo "$uids" | grep -c '[a-z0-9]' || true)
  [[ $count -eq 0 ]] && break
  echo "$uids" >> /tmp/uids.txt
  offset=$((offset + count))
done
sort -u /tmp/uids.txt | wc -l

Found 11 locations in getLocations missing from getLocationMapPoints — all had publish: false. Different filtering semantics by design, not a bug.

  1. Check endpoint defaults and limits — endpoints in the same family can have different defaults.
# locations  → default 100, max 100  (400 if limit > 100)
# map-points → default 500, max 500  (400 if limit > 500)

getLocationMapPoints was returning 5× more items per request than getLocations.

  1. Run a controlled experiment with matched page sizes — pin limit to the same value across both before drawing any conclusions.

Four pairings at 20 RPS, 30s each (ev/page_size_test.js):

Pairinglocations p99map-points p99
Default (no params)1.44s1.79s
Offset only ?offset=rand(0-20)864ms2.18s
Limit only ?limit=100900ms673ms
Offset + limit ?offset=rand(0-20)&limit=100953ms497ms

Key findings

Page size was the entire problem. limit=100 alone dropped map-points p99 from 1.79s → 673ms (~2.7×). No query changes needed.

Warning

Offset without limit makes things worse — map-points still returns 500 items but now scans past extra rows first. Never add offset without also setting limit.

At equal page size, map-points is faster than locations. Map-points returns 4 fields per item vs locations’ 25+. Lighter payload wins at every percentile once page size is controlled.

Locations has no room to improve via page size — it already defaults to its max of 100. Its latency floor is payload weight per item.

The fix

Lower MAP_POINTS_MAX_LIMIT from 500 → 100 in voltnet-omni/pkg/configs/configs.go. No query layer changes needed.

See also