Serverless Weather Reporting with AWS Step Functions and CDK
March 05, 2023
Photo by Devin Justesen on Unsplash
I live in the Pacific Northwest. Approximately 1-2 times per year, it snows. When this happens, people act shocked because “it never happens here.”* Our local governments do not have many snow plows nor do they salt the roads much. This means that when it snows, the roads are highly dangerous. The city of Portland, Oregon often shuts down for multiple days.
Former residents of Portland created a website, isitsnowinginpdx.com. I cannot speak for their motivations, but I find this site both entertaining and informative.
After moving out of Portland into the suburbs, I noticed that the site was not as accurate, so I decided to build my own site isitsnowinginhillsboro.com.
Behind the scenes, this site is using AWS Serverless technologies. S3 hosts site assets, a Step Function updates the site, and EventBridge Scheduler triggers the Step Function every 10 minutes.
I made the decision to not put CloudFront in front of this S3 Bucket, because this is a region specific website. Most people viewing this site live in the area and adding a CDN feels like unnecessary complexity given the use case. As a result, the site renders of
HTTP rather than
Here’s a breakdown of what the Step Function workflow does:
- Get the site’s current status (
no snow) from a DynamoDB table
- Check the current weather using the OpenWeatherMap API via a Lambda Function
- A choice state compares the two values
- If the two values match, nothing happens and the workflow ends
- If the two values do not match, it updates the site to show the current weather obtained from the API
- A Lambda Function generates the HTML and places that HTML file into an S3 bucket (more on this later)
- If the Lambda Function is successful, then it updates the site status in DynamoDB
Here’s a visual representation of the workflow:
Overall things went smoothly. I did run into a few tiny issues.
Issue 1: EventBridge Scheduler and CDK
EventBridge Scheduler is a new-ish feature and does not have an L2 construct. I was able to implement what I needed for this site using an L1 construct, but with an L1 construct you’re writing Cloudformation without the benefits that an L2 construct provides. In this case, I had to define an IAM Role to allow the Scheduler to invoke the Step Function and an inline policy. This is likely a feature that would be included in an L2 construct.
More info on L1 vs L2 constructs here. I plan to keep an eye on this open RFC.
Issue 2: HTML Generation
Step Functions have direct integrations with many services. The advantage of this is you do not have write a Lambda Function to make those AWS SDK calls and can save money as well as enjoy the built in error/retry logic that comes with the Step Function service. I used the direct integration for the two calls to DynamoDB and it worked quite well.
When it came to generating HTML and using the S3 PutObject, the direct integration added quotes around the HTML. This resulted in an HTML document that looked similar to
"<h1>My site<h1>". The extra quotation marks caused the page to not render properly in the browser. I eventually got this working with a Lambda Function by sending the Body as a Buffer, but I prefer the direct integration.
The code is open source and you can view it here.
You can clone the repo following the instructions in the README.md file to create your own weather site. Plug in the latitude and longitude of your city. Also, it’s not limited to snow! Check out the
Main weather types here for all available options.
Open source contributions are welcome.
Thanks to the original creators of isitsnowinginpdx.com for the inspiration.
* To be fair the last instance of snow in the area was more than usual.