Angular weather-intouch 2026-06-02 · 5 min čtení

Free data jako páteř, placené API jen na špičku — a co když odpadne

Open-Meteo pokryje většinu předpovědi zdarma. Placené OpenWeather se sáhne jen na pár okamžitých hodnot — a když odpadne, appka jede dál.

Páteř zdarma: Open-Meteo

Při vývoji meteorologických aplikací dříve či později narazíte na finanční a výkonnostní limity datových zdrojů. Poskytovatelé přesných meteorologických dat si za svá API nechávají dobře zaplatit. Pokud vaše klientská základna roste, účty za tisíce požadavků mohou rychle smazat jakoukoli ekonomickou udržitelnost projektu. Naštěstí moderní softwarová architektura umožňuje tento problém vyřešit hybridním přístupem. Správná kombinace Open-Meteo a OpenWeather nabízí rovnováhu mezi nulovými či nízkými provozními náklady a vysokou přesností tam, kde na ní uživateli nejvíce záleží.

Open-Meteo slouží v tomto návrhu jako bezplatná páteř celého systému. Toto API vyniká skvělou dostupností, v základním režimu nevyžaduje složitou správu API klíčů a nabízí robustní globální datové sady založené na otevřených fyzikálních modelech, jako jsou GFS nebo ECMWF. Z Open-Meteo se stahuje kompletní kostra předpovědi, která obsahuje aktuální stav, podrobnou hodinovou předpověď a denní výhled na sedm dní dopředu. Pro naprostou většinu zobrazovaných informací je tento zdroj zcela dostačující a pro koncového uživatele představuje stabilní základ, který pokrývá hlavní část jeho informačních potřeb.

Placený overlay jen na okamžité hodnoty

Ačkoli jsou globální otevřené modely velmi přesné pro trendy a dlouhodobější výhledy, u okamžitého stavu počasí (tzv. nowcasting) mohou vykazovat drobné zpoždění oproti realitě na konkrétním místě. V tuto chvíli přichází na řadu placené API od OpenWeather. To disponuje hustou sítí lokálních meteostanic a radarů, díky čemuž dokáže poskytnout velmi přesné a aktuální hodnoty pro danou minutu.

Namísto toho, abychom z placeného API stahovali kompletní týdenní předpověď, což by při vyšší návštěvnosti generovalo neudržitelné náklady, využíváme OpenWeather pouze jako tenký overlay (překryvnou vrstvu). Z placeného zdroje se dotazujeme výhradně na aktuální stav pro danou lokalitu.

V praxi to znamená, že systém nejprve sestaví kompletní datovou strukturu z bezplatného Open-Meteo. Následně vezme několik vybraných okamžitých hodnot z OpenWeather (například přesnou aktuální teplotu, pocitovou teplotu a kód aktuálního stavu počasí) a těmito daty přepíše odpovídající pole v původním objektu. Zbytek předpovědi, včetně datově náročných hodinových a denních matic, zůstává nedotčen. Výsledkem je vysoká přesnost v detailu aktuálního počasí při zachování minimálních provozních nákladů.

Best-effort: co selže, to se tiše vynechá

Jedním ze základních pravidel robustní backendové architektury je předpoklad, že jakákoli externí služba může kdykoli selhat. Placené API může vyčerpat nastavené limity, může dojít k výpadku sítě nebo k dočasnému zvýšení latence na straně poskytovatele. Uživatel by však takový výpadek neměl vůbec zaznamenat.

Všechny doplňkové datové vrstvy, ať už se jedná o placený overlay z OpenWeather, index kvality ovzduší (AQI), nebo oficiální meteorologické výstrahy, jsou proto navrženy v režimu best-effort. Pokud volání těchto doplňkových služeb selže, aplikace nesmí vrátit chybový stav ani zobrazit uživateli prázdnou obrazovku.

Backend tyto chyby tiše zachytí, zaloguje je pro účely interního monitoringu a pokračuje v sestavování odpovědi bez nich. Klient v takovém případě dostane kompletní a plně validní předpověď vygenerovanou výhradně z páteřního Open-Meteo. Uživatelský zážitek zůstává zachován, aplikace funguje dál a systém vykazuje vysokou odolnost proti výpadkům třetích stran.

Placené volání jen v refresh cestě

Abychom předešli nechtěnému finančnímu zatížení, je nutné striktně oddělit cestu pro čtení dat od cesty pro jejich aktualizaci. V komplexnějších systémech postavených například na kombinaci NestJS, MongoDB a Redis hrozí riziko, že neopatrný vývojář zavolá drahé externí API přímo z controlleru, který obsluhuje běžné uživatelské dotazy na čtení. Při náhlém nárůstu návštěvnosti by takový návrh mohl vést k okamžitému vyčerpání rozpočtu.

Placené volání je proto v architektuře injektováno výhradně do takzvané refresh cesty na serveru. Běžný read-endpoint, na který se dotazuje klientská aplikace, nemá k API klientovi placené služby vůbec přístup. Pouze čte předpřipravená data z databáze nebo cache.

K aktualizaci dat dochází kontrolovaně na pozadí, případně přes specifický refresh mechanismus, který je chráněn přísným rate-limitingem. Tímto způsobem je zajištěno, že se drahé API volá pouze tehdy, když je to skutečně nutné, a to maximálně jedním voláním placeného API na lokalitu v definovaném časovém okně. Controller pro běžné čtení tak nikdy nemůže omylem vygenerovat zbytečné náklady.

Mapper jako jediné místo normalizace

Různí poskytovatelé meteorologických dat používají odlišné formáty odpovědí. Zatímco Open-Meteo vrací data v plochých polích, kde indexy reprezentují časové řady, OpenWeather spoléhá na hluboce zanořené JSON objekty. Pokud by se tyto formáty míchaly napříč aplikací, kód by se rychle stal neudržovatelným.

Řešením je striktní normalizace dat na vstupu do systému. K tomuto účelu slouží dedikovaná mapovací vrstva. Tento mapper je jediným místem v celé aplikaci, které zná specifika jednotlivých externích API. Přijme surová data z obou zdrojů, provede jejich validaci, transformaci a sloučí je do jednoho sdíleného objektu pro přenos dat (DTO).

Následující ukázka ilustruje zjednodušený koncept takového mapperu v TypeScriptu:

interface WeatherDTO {
  temperature: number;
  windSpeed: number;
  weatherCode: number;
  hourlyForecast: { time: string; temp: number }[];
}

interface OpenMeteoRaw {
  current: { temperature_2m: number; wind_speed_10m: number; weather_code: number };
  hourly: { time: string[]; temperature_2m: number[] };
}

interface OpenWeatherRaw {
  main: { temp: number };
  wind: { speed: number };
  weather: { id: number }[];
}

export class WeatherMapper {
  public static mapToDto(
    openMeteoRaw: OpenMeteoRaw,
    openWeatherRaw?: OpenWeatherRaw,
  ): WeatherDTO {
    // Základní kostra z bezplatného Open-Meteo
    const dto: WeatherDTO = {
      temperature: openMeteoRaw.current.temperature_2m,
      windSpeed: openMeteoRaw.current.wind_speed_10m,
      weatherCode: openMeteoRaw.current.weather_code,
      hourlyForecast: openMeteoRaw.hourly.time.map((time: string, index: number) => ({
        time,
        temp: openMeteoRaw.hourly.temperature_2m[index]
      }))
    };

    // Pokud je k dispozici placený overlay, přepíšeme vybrané hodnoty
    if (openWeatherRaw && openWeatherRaw.main) {
      dto.temperature = openWeatherRaw.main.temp;
      dto.windSpeed = openWeatherRaw.wind.speed;
      dto.weatherCode = this.mapOpenWeatherCode(openWeatherRaw.weather[0].id);
    }

    return dto;
  }

  private static mapOpenWeatherCode(code: number): number {
    // Interní převodní logika kódů počasí na jednotný standard
    return code; 
  }
}

Zbytek aplikace, včetně frontendové části a databázových modelů, již pracuje výhradně s tímto unifikovaným DTO. Pokud se v budoucnu rozhodnete vyměnit OpenWeather za jiného placeného poskytovatele, změna se dotkne pouze tohoto jediného souboru. Architektura zůstává čistá a snadno rozšiřitelná.

Tento robustní přístup k integraci a normalizaci dat byl úspěšně nasazen v rámci platformy, kterou detailně popisuje celý projekt Weather InTouch. Kombinace spolehlivého bezplatného základu s precizním placeným překryvem se v praxi ukázala jako nejlepší způsob, jak vybudovat škálovatelnou a ekonomicky udržitelnou službu, která netrpí na výpadky externích poskytovatelů.

Související články

Kontaktní informace

Klidně se mi ozvěte ohledně nového projektu, konzultace nebo dlouhodobější spolupráce. Rád proberu smysluplné produktové zadání i zajímavé frontendové příležitosti.

Napište mi

© 2026 Martin Hubálek. Všechna práva vyhrazena.