Skip to content
Bryan Brkic
All work

Pelmorex Corp — The Weather Network

Systems I helped scale at The Weather Network

Precipitation alerts were not the only thing that had to keep pace with the weather. Alongside that platform, I took senior ownership of four more systems: the government alert channel, the Maps SDK, the content API behind the app's articles, and the search infrastructure behind every location lookup.

Role
Senior ownership, four systems
Scope
Government alerts, maps, content API, search
Period
Oct 2022 — Present
Core stack
TypeScript, Python, Go, AWS, Terraform, PostgreSQL, React

Government alerts

A second alert channel, one publishing layer

Environment Canada, the US National Weather Service, Canada's national public alerting system and MeteoAlarm in Europe each speak their own dialect of the Common Alerting Protocol. A router service normalises all four into one internal schema and fans them out by source, then a notification service resolves the affected locations and hands off to the same Firebase Cloud Messaging layer the precipitation platform uses.

Government alert pipelineA router normalises and compacts alerts from Environment Canada, the US National Weather Service, NAADS and MeteoAlarm into a queue per source. A notification service resolves affected locations, and the result is handed to the same push layer the precipitation platform uses.Alert routerFilter, dedupe, compactSQS FIFOEnvironment CanadaSQS FIFOUS NWSSQS FIFONAADSSQS FIFOMeteoAlarmNotification serviceNormalise + resolve locationsPush serviceBatches topicsFCMPush to the phone
Four CAP dialects in, one push notification outScroll the diagram sideways →
  • Four sources, one schema: Environment Canada, NWS, NAADS and MeteoAlarm are normalised into a common alert model despite very different severity and geocoding conventions.
  • Payload compaction: government alerts arrive far larger than a queue message can carry, so geometry and attachments no downstream consumer ever read are stripped on the way in — an order of magnitude smaller, without losing anything that mattered.
  • One publishing layer: this pipeline and the precipitation platform both end at the same push service, batched and sent with platform-specific payloads for Android and iOS. Delivery from alert to phone lands within about a minute.

Maps

The layers people actually open

Alerts tell you something is coming. Maps are how people decide what to do about it. I took senior ownership of the Maps SDK behind theweathernetwork.com — a MapLibre GL front end with MapTiler Weather's WebGL layers on top, so radar animates as a real loop instead of a flipbook of images and wind renders as a live particle field instead of an arrow grid. The live radar map is the clearest place to see it running.

Maps SDK infrastructureThe browser talks to four edges: a CDN in front of object storage for the React app, a CDN in front of the map API, a CDN and load balancer in front of the basemap tile cluster, and a vector-tile service for point and track layers. Behind the map API, a services cluster dispatches work to a processing cluster, which writes into the same bucket the map API reads from.BrowserCloudFrontS3 · React appCloudFrontECS · Maps APICloudFront + ALBECS · Basemap tilesVector tile servicePoint & track layersECS · ServicesDispatch and refreshECS · ProcessingDispatched tasksS3Maps data bucket
Four edges the browser talks to, one data pipeline behind themScroll the diagram sideways →
  • MapLibre GL renders the base map; MapTiler Weather's custom WebGL layers handle radar, precipitation, cloud and temperature tiles.
  • Wind renders as a live GPU particle field rather than a static arrow grid.
  • Road conditions, wildfire pins and hurricane forecast tracks come from a dedicated vector-tile service, each with their own popup.
  • Polling pauses when the tab is hidden and refreshes instantly when you come back, so the map is never stale without also being wasteful.
  • Radar
  • Precipitation
  • Cloud
  • Temperature
  • Wind
  • Road conditions
  • Wildfire smoke
  • Hurricane forecasts

Content platform

An event-driven content API

Editorial content published in Contentful — articles, editorial lineups, promotional material — arrives continuously, and every downstream consumer wants it in a slightly different form. Rather than let those consumers call each other, updates are published once and fanned out. It is the API behind the news section of theweathernetwork.com.

Event-driven content management pipelineA content update published in the CMS enters through API Gateway and a Lambda function, which publishes to an SNS topic. The topic fans out to SQS queues, each with its own Lambda consumer writing results to S3, which CloudFront serves. Where a consumer needs consumers of its own, the same pattern repeats before those results land in the same bucket.CMSEditorial publishAPI GatewayWebhook intakeLambdaPublishes updateSNS topicFan-out pointSQS queueConsumer group ASQS queueConsumer group BSQS queueConsumer group CLambdaWrites to S3LambdaTriggers 2nd waveLambdaWrites to S3S3Durable outputCloudFrontServes the bucketSNS topicSecond waveSQS queueConsumer group DSQS queueConsumer group ELambdaWrites to S3LambdaWrites to S3S3Same bucket
Content update path — CMS to CloudFront, with a second wave of fan-outConsumer groups simplified for clarity.Scroll the diagram sideways →
  • API Gateway takes the publish webhook and a Lambda puts it on an SNS topic, so producers never need to know who is listening.
  • SNS fans out to a queue per consumer group, which means a slow consumer backs up its own queue instead of everyone else's.
  • Where one consumer's output needs consumers of its own, the same fan-out repeats rather than becoming a special case.
  • Every Lambda writes durable output to S3, which CloudFront then serves so readers hit a cache instead of the pipeline that keeps it fresh.

Search

Moving search off Kubernetes

The search behind the app's location lookup — the dropdown that turns “toront” into Toronto, ON before you have finished typing — was running on Kubernetes, and it cost more attention to keep healthy than it was worth. I re-architected it onto AWS end to end: infrastructure, database and the SQL that actually ranks results.

Search API infrastructureClient apps call one of two independent regional stacks, one US and one Canadian, each a CloudFront distribution in front of an ALB, in front of an autoscaled ECS search service reading from its own Aurora Postgres cluster with separate schemas per environment. Metrics from both regions feed one set of cross-region CloudWatch dashboards.Client appsLocation searchCloudFrontUS regionALBTLS terminationECS · Search APIAutoscaledAurora PostgresSchema per environmentCloudFrontCanadian regionALBTLS terminationECS · Search APIAutoscaledAurora PostgresSchema per environmentCloudWatchCross-region dashboards
Two independent regions, one set of dashboardsScroll the diagram sideways →

Data

  • Aurora Postgres
  • Two regions
  • Schema-separated environments

One cluster per region serves both staging and production through separate schemas, so there is no second database to pay for or keep in sync.

Compute

  • ECS
  • ALB
  • Auto Scaling

Provisioned in both regions from the same Terraform modules.

Matching

  • Trigram
  • Fuzzy
  • Phonetic

Tuned in SQL so a typo like “tornoto” still resolves to Toronto, and results come back ranked the way the product actually wanted.

  • Terraform-managed modules for the registry, the database and the service replaced a Kubernetes deployment that needed constant attention.
  • CloudWatch dashboards and alarms across both regions replaced tribal knowledge with something the whole team could look at.

Infrastructure

Environments that come from code

Government alerts, maps, content and search all run as microservices across multiple environments, provisioned with Terraform. Standing up a new environment is a configuration change rather than an afternoon of clicking through the console, and the difference between staging and production is something you can read in a diff.

  • A multi-environment AWS estate defined as Terraform modules across many repositories, applied through the same path every time.
  • Service APIs behind managed load balancing with autoscaling sized to real traffic shapes rather than guesses.
  • Queues, topics, buckets, roles and networking all declared alongside the services that use them.

Developer tooling

A reviewer that reads the ticket first

Reviews slow down when the reviewer has to reconstruct intent from a diff. I built a service that does the reconstruction up front: it listens to Bitbucket webhooks, pulls the acceptance criteria from the linked Jira issue, reads the diff, and returns structured findings pinned to specific files and lines.

It is written in Python with FastAPI, orchestrated with LangChain, and every model response is parsed through Pydantic schemas, so the output is data the pipeline can act on rather than prose a human has to interpret.

Next case study

Korsara, a platform for people who sell what they know

Read it

Get in touch

If any of this is the kind of problem you are hiring for, I would like to hear about it.

brkicb1@gmail.com