Apparent latency issue with alerts

I am having a lot of trouble with alerts showing up after a successful delete. I have two scripts to demonstrate the problems …

#!/usr/bin/env bash
set -euo pipefail

# --- Config ---
AEROAPI_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxx"
ALERT_ID="${1:?Usage: $0 <alert_id>}"
BASE_URL="``https://aeroapi.flightaware.com/aeroapi``"

echo "==> Deleting alert ${ALERT_ID}..."
delete_response=$(curl -s -w "\n%{http_code}" \
-X DELETE \
-H "x-apikey: ${AEROAPI_KEY}" \
"${BASE_URL}/alerts/${ALERT_ID}")

delete_body=$(echo "$delete_response" | sed '$d')
delete_status=$(echo "$delete_response" | tail -n1)

echo "Delete status: ${delete_status}"
if [ -n "$delete_body" ]; then
echo "Delete body: ${delete_body}"
fi

if [ "$delete_status" != "204" ]; then
echo "ERROR: Expected 204 No Content from delete, got ${delete_status}" >&2
exit 1
fi

echo "==> Retrieving alert ${ALERT_ID} to confirm deletion..."
get_response=$(curl -s -w "\n%{http_code}" \
-X GET \
-H "x-apikey: ${AEROAPI_KEY}" \
"${BASE_URL}/alerts/${ALERT_ID}")

get_body=$(echo "$get_response" | sed '$d')
get_status=$(echo "$get_response" | tail -n1)

echo "Get status: ${get_status}"
echo "Get body: ${get_body}"

if [ "$get_status" == "404" ]; then
echo "Confirmed: alert ${ALERT_ID} no longer exists."
elif [ "$get_status" == "200" ]; then
echo "WARNING: alert ${ALERT_ID} still exists after delete!" >&2
exit 1
else
echo "Unexpected status on GET: ${get_status}" >&2
exit 1
fi
… with the following result:

==> Deleting alert 122418488...
Delete status: 204
==> Retrieving alert 122418488 to confirm deletion...
Get status: 200
Get body: {"id":122418488,"description":"Virgin Atlantic 3 (EGLL → KJFK)","ident":"VIR3","ident_icao":"VIR3","ident_iata":"VS3","origin":"EGLL","origin_icao":"EGLL","origin_iata":"LHR","origin_lid":null,"destination":"KJFK","destination_icao":"KJFK","destination_iata":"JFK","destination_lid":"JFK","aircraft_type":null,"created":"2026-06-29T16:00:04Z","changed":"2026-06-29T16:00:04Z","start":"2026-06-29","end":null,"user_ident":null,"eta":0,"impending_arrival":null,"impending_departure":null,"events":{"arrival":true,"cancelled":true,"departure":true,"diverted":true,"filed":true,"out":true,"in":true,"off":false,"on":false,"hold_start":true,"hold_end":true},"target_url":"https://api-dev.chippytrip.com/api/watch-callback?s=52909c11552405b1fc1ff9c1f561c5d2","enabled":true}
WARNING: alert 122418488 still exists after delete!


… and …

#!/usr/bin/env bash



check_alert_consistency.sh



Demonstrates a FlightAware AeroAPI inconsistency where a deleted alert

still appears in GET /alerts (list) but 404s when fetched individually

via GET /alerts/{id}.



Usage:

export AEROAPI_KEY="your-api-key-here"

./check_alert_consistency.sh



Optional: pass a specific alert ID to check instead of the first one

in the list:

./check_alert_consistency.sh 123456



Requires: curl, jq

set -euo pipefail

BASE_URL="https://aeroapi.flightaware.com/aeroapi"

if [[ -z "${AEROAPI_KEY:-}" ]]; then
echo "Error: AEROAPI_KEY environment variable is not set." >&2
echo "  export AEROAPI_KEY="your-api-key-here"" >&2
exit 1
fi

for cmd in curl jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "Error: required command '$cmd' not found in PATH." >&2
exit 1
fi
done

echo "=== Step 1: Fetching alert list ==="
LIST_RESPONSE=$(curl -s -w "\n%{http_code}" 
--request GET 
--url "${BASE_URL}/alerts" 
--header "x-apikey: ${AEROAPI_KEY}" 
--header "Accept: application/json")

LIST_HTTP_CODE=$(echo "$LIST_RESPONSE" | tail -n1)
LIST_BODY=$(echo "$LIST_RESPONSE" | sed '$d')

echo "HTTP status: ${LIST_HTTP_CODE}"

if [[ "$LIST_HTTP_CODE" != "200" ]]; then
echo "Error: failed to fetch alert list." >&2
echo "$LIST_BODY" >&2
exit 1
fi

ALERT_COUNT=$(echo "$LIST_BODY" | jq '.alerts | length')
echo "Alerts returned in list: ${ALERT_COUNT}"

if [[ "$ALERT_COUNT" -eq 0 ]]; then
echo "No alerts in list. Nothing to check."
exit 0
fi

Allow overriding which alert to check via first CLI arg, otherwise use

the first alert in the list.

if [[ $# -ge 1 ]]; then
ALERT_ID="$1"
echo "Using alert ID passed on command line: ${ALERT_ID}"
else
ALERT_ID=$(echo "$LIST_BODY" | jq -r '.alerts[0].id')
echo "Using first alert ID from list: ${ALERT_ID}"
fi

echo
echo "--- Alert object as returned by list endpoint ---"
echo "$LIST_BODY" | jq --arg id "$ALERT_ID" '.alerts
 | select(.id == ($id | tonumber))'

echo
echo "=== Step 2: Fetching that alert individually ==="
GET_RESPONSE=$(curl -s -w "\n%{http_code}" 
--request GET 
--url "${BASE_URL}/alerts/${ALERT_ID}" 
--header "x-apikey: ${AEROAPI_KEY}" 
--header "Accept: application/json")

GET_HTTP_CODE=$(echo "$GET_RESPONSE" | tail -n1)
GET_BODY=$(echo "$GET_RESPONSE" | sed '$d')

echo "HTTP status: ${GET_HTTP_CODE}"
echo "Response body:"
echo "$GET_BODY" | jq . 2>/dev/null || echo "$GET_BODY"

echo
echo "=== Result ==="
if [[ "$GET_HTTP_CODE" == "404" ]]; then
echo "INCONSISTENCY CONFIRMED: alert ${ALERT_ID} appears in the list"
echo "endpoint (HTTP ${LIST_HTTP_CODE}) but returns 404 on direct lookup."
elif [[ "$GET_HTTP_CODE" == "200" ]]; then
echo "No inconsistency observed for alert ${ALERT_ID}: it exists in"
echo "both the list and the direct lookup."
else
echo "Unexpected status ${GET_HTTP_CODE} on direct lookup -- inspect"
echo "the response body above."
fi

… with the result …

=== Step 1: Fetching alert list ===
HTTP status: 200
Alerts returned in list: 17
Using first alert ID from list: 122580156

--- Alert object as returned by list endpoint ---
{
"id": 122580156,
"description": "British Airways 117 (EGLL → KJFK)",
"ident": "BAW117",
"ident_icao": "BAW117",
"ident_iata": "BA117",
"origin": "EGLL",
"origin_icao": "EGLL",
"origin_iata": "LHR",
"origin_lid": null,
"destination": "KJFK",
"destination_icao": "KJFK",
"destination_iata": "JFK",
"destination_lid": "JFK",
"aircraft_type": null,
"created": "2026-06-30T17:00:06Z",
"changed": "2026-06-30T17:00:06Z",
"start": "2026-06-30",
"end": null,
"user_ident": null,
"eta": 0,
"impending_arrival": null,
"impending_departure": null,
"events": {
"arrival": true,
"cancelled": true,
"departure": true,
"diverted": true,
"filed": true,
"out": true,
"in": true,
"off": false,
"on": false,
"hold_start": true,
"hold_end": true
},
"target_url": "https://api-dev.chippytrip.com/api/watch-callback?s=e8908cb615cb3fb7b52529e60f71ebaf",
"enabled": true
}

=== Step 2: Fetching that alert individually ===
HTTP status: 404
Response body:
{
"title": "Not Found",
"reason": "NOT_FOUND",
"detail": "No such alert exists",
"status": 404
}

=== Result ===
INCONSISTENCY CONFIRMED: alert 122580156 appears in the list
endpoint (HTTP 200) but returns 404 on direct lookup.

Sometimes they are sticking around for hours. This only started happening in the last week or so. It’s making development very difficult. Any ideas?