Caching & monitoring
Airport 404 fallbacks and validation errors: Error handling. Platform HTTP errors and retries: Error Handling.
Data freshness
Airport records, navaid data, and search indexes are updated periodically — not in real time. Cache aggressively; airport metadata rarely changes day-to-day.
| Endpoint | Recommended TTL | Notes |
|---|---|---|
GET /airports/search | 24 hours | Static metadata: runways, frequencies, elevation |
GET /airports/search/text | 1 hour | Search index is stable; results won't shift within a session |
GET /navaids | 6 hours | Navaid data is updated on aeronautical-cycle schedules |
GET /airports/search/location | 15 minutes | Nearest-airport results depend on user location; re-run when coordinates change |
Caching
Use a simple in-process TTL cache for low-volume integrations. For multi-instance deployments, replace the dict with Redis or Memcached so the cache is shared and survives restarts.
import os
import time
import requests
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
_cache: dict[str, tuple[dict, float]] = {}
def cached_get(url: str, params: dict, ttl_seconds: int) -> dict | None:
"""Fetch with a simple in-process TTL cache. Returns None on 404."""
key = url + str(sorted(params.items()))
cached = _cache.get(key)
if cached and time.time() < cached[1]:
return cached[0]
r = requests.get(url, headers=HEADERS, params=params, timeout=(10, 15))
if r.status_code == 404:
return None
r.raise_for_status()
data = r.json()
_cache[key] = (data, time.time() + ttl_seconds)
return data
def get_airport(icao: str) -> dict | None:
return cached_get(f"{BASE}/airports/search", {"icao": icao}, ttl_seconds=86400)
def search_airports(query: str) -> list[dict]:
data = cached_get(f"{BASE}/airports/search/text", {"q": query}, ttl_seconds=3600)
return (data or {}).get("airports") or []
def get_navaids(icao: str) -> list[dict]:
data = cached_get(f"{BASE}/navaids", {"airport": icao}, ttl_seconds=21600)
return (data or {}).get("navaids") or []Rate limits
Every response includes rate-limit headers. See Error Handling for quota tiers and the 429 retry pattern.
| Header | Value |
|---|---|
X-RateLimit-Requests-Limit | Your plan's monthly request quota |
X-RateLimit-Requests-Remaining | Requests left this month |
X-RateLimit-Requests-Reset | Seconds until the quota resets |
Because airport data has a long TTL, a well-cached integration uses very few requests per session. A single /airports/search response for a given ICAO can be safely reused for the rest of the day.
Runnable example
Fetches KJFK with a 24-hour TTL cache, prints cache hit/miss on each call.
import os
import time
import requests
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
_cache: dict[str, tuple[dict, float]] = {}
def get_airport(icao: str) -> dict | None:
url = f"{BASE}/airports/search"
key = f"airport:{icao}"
cached = _cache.get(key)
if cached and time.time() < cached[1]:
print(f" cache HIT — {icao}")
return cached[0]
print(f" cache MISS — {icao}, fetching...")
r = requests.get(url, headers=HEADERS, params={"icao": icao}, timeout=(10, 15))
if r.status_code == 404:
return None
r.raise_for_status()
data = r.json()
_cache[key] = (data, time.time() + 86400)
return data
if __name__ == "__main__":
airport = get_airport("KJFK")
if airport:
print(f" {airport.get('name')} — elevation {airport.get('elevation_ft')} ft")
# Second call — served from cache
airport = get_airport("KJFK")
if airport:
print(f" {airport.get('name')} — served from cache")Monitoring
Log these fields on every airport API request:
import logging
import time
import requests
logger = logging.getLogger("airport")
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_airport_logged(icao: str) -> dict | None:
start = time.monotonic()
r = requests.get(
f"{BASE}/airports/search",
headers=HEADERS,
params={"icao": icao},
timeout=(10, 15),
)
elapsed_ms = (time.monotonic() - start) * 1000
log_data = {
"endpoint": "airports/search",
"icao": icao,
"status": r.status_code,
"elapsed_ms": round(elapsed_ms),
"quota_remaining": r.headers.get("X-RateLimit-Requests-Remaining"),
}
if r.status_code == 200:
logger.info("airport_fetch", extra=log_data)
return r.json()
elif r.status_code == 404:
logger.info("airport_not_found", extra=log_data)
return None
else:
logger.warning("airport_error", extra=log_data)
r.raise_for_status()Alert on:
status = 429— your polling rate exceeds your plan; increase TTL or upgradeelapsed_ms > 5000repeatedly — upstream latency; consider a timeout and fallbackquota_remaining < 200— approaching your monthly limit
Related: Airports · Airport Search · Navaids · Error handling