GET /weather/location/:{location} - fetches current forecast for a specific location
GET /weather/location/:{location}/period/:{period} - fetches forecast for a location for a specific period of time, eg next 7 days
for geocoding we could use google maps api which translates cities or addresses to coordinates. these will afterwards be forwarded to a third party for fetching the forecast
POST /notifications/:{userId} - users will save their notification preferences:
body:{
notificationType: string;
isActive: boolean;
}
notifications will be pushed by a notification service directly to users if the notification is set on when severe events occur or weather changes
POST /normalize-location - endpoint that normalizes the locations and encodes them whenever it is needed. we can make an api call to google maps api to resolve names to coordinates and the endpoint will cache those responses and return the cached response afterwards
the clients will be of 3 types: web, mobile and weather sensors. these will make calls to DNS with the domain names and will get on response the translated IPs.
A CDN will make the process faster, it will deliver the static pages and all the needed images, eg mappings to rain, snow, sun images/videos.
Load balancer is needed between the clients and API Gateway to support scalability and high availability.
API Gateway handles authentication and rate limiting, and it will forward the calls to Geocoding Service and to Weather Service. by calling their methods.
Geocoding Service will translate location names to encoded locations with specific ids (like google maps API does). this component will call geocoding API which makes the actual call to a third party and caches the result. aftwards, this specific result will be used by the weather service which will call weather API if we use a third party, it will update the DB, cache results to redis, and in case of missing cache will read results from readonly DB(for notification preferences).
cronjob service will call periodically the weather api and update the locations' forecasts in db.
in case of extreme weather alerrts, the weather service will push a message to the queue (eg sqs from aws ) and notification service will consume it and forward to websocket gateway which will push it to users in real time, either by sms or push notifications
for historical data, weather service will check the db and return responses with old data (weather forecasts). analytics can also use that db data
the cache can be done using redis and it will return data if it is already saved and not older than eg one hour, otherwise that data will be invalidated and fresened up. a SQL db would be more useful here as the data has a strict form, eg weather table: cityName, cityId, country, weather, lastUpdated. notification preferances table: userId, notificationType, isEnabled
notification: notificationId, userId, deliveredAt
microservice architecture is used here, having one microservice for weather and one for notifications. by decoupling the services they are more scalable in cases of high spikes, also using a queue here decouples the notification delivery making it async.
the API gateway acts as a single entry point for all client requests, directing them to the geocoding service and to the weather one. this design enables load balancing ensuring that incoming requests are distributed evenly across multiple instances of the weather service.
the weather service is responsable for fetching the data and saving it to db and also caches it to redis, minimizing latency.
when updating weather info, we will use an idempotency key, in this case it can be the location id and the timestamp of the last update, in case of conflicts we will use the latest update. there will be no duplicates because the location and timestamp will be used as a primary composed key. staleness wll be handled by cronjobs calling the weather api service. also on each update, the previous values will be invalidated if they are stale, and the cache will be updates
the cache can be done using redis, we can use a key value mapping, the key will be the location and value will be the weather forecast and a timestamp. we can set the invalidation time to 1 hour and invalidate everything then. also if there is a request to weather api which returns a different response from the cached one, we will invalidate the current cache and update it again. cronjobs will also bring the latest data every hour. the format will be:
temperature, wind speed, precipitations percentage, extraDetails. all 3rd party responses will be cast to the upper format before saving them to the cache.
in case of 3rd party api failures, the users will be served using cached responses whilst retrying to call the api and update the caches
notifications will be decoupled and served asynchronously using a message queue, for example sqs from aws, this way the message will be pushed in a queue which in an async manner will consume them and push to the user, or send sms.
the notification service is in a separate microservice and can be scaled up in case of high demands and usage spikes, by adding multiple instances.
the high demanded locations should be updated by leveraging transactions in such manner that multiple people trying to fetch the same city weather whilst the cache has just been invalidated and needs to call the api in order to rewrite it. for example if multiple users ask for the same resource, until the api responds and rewrites the cache, we could use a transaction and lock that db entry
to prevent retries writing duplicates, we would use an upsert, this way if the entry doesnt exist, it creates it, if it exists, it updates it. this way it wont create new resources and it will prevent duplicates