
š» GitHub Repo: Check out the full source code here
Let’s Get Started
Letās build something meaningful and scalable togetherāa production-grade serverless weather alert system on AWS. This isnāt just a āfollow the stepsā tutorialāitās us walking through smart decisions at every layer of this cloud-native solution. From ingestion to alerts, transformations to dashboards, weāll explore every architectural building block in a way thatās fun and real.
This system is built using AWS best practices, keeping in mind the Well-Architected Framework, and it’s all fully reproducible using infrastructure as code.
š What Are We Building?
Weāre building a system where visitors can subscribe to get weather updates via emailādaily forecasts and instant alerts for any severe conditions. Instead of asking users to manually select their country, weāll use geolocation via ip-api.com based on their IP during signup. Our emails will be easy to unsubscribe from, thanks to secure tokenized links.
š Letās Handle Subscriptions
Our journey begins with a WordPress-embedded form. When someone subscribes, their details are sent to an API Gateway endpoint, which then triggers a Lambda function. This function extracts the email and automatically determines the userās country using ip-api.com. All this info is then saved securely in a DynamoDB table.
š§© CDK Snippet:
const subscriptionLambda = new lambda.Function(this, 'SubscriptionLambda', {
runtime: lambda.Runtime.PYTHON_3_11,
handler: 'subscription.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/subscription')),
environment: {
DDB_TABLE_NAME: table.tableName,
SENDER_EMAIL: senderEmail,
},
});
We chose DynamoDB over RDS and Aurora Serverless because:
- Itās serverless and auto-scales
- It has built-in high availability
- Itās great for key-based lookups like checking if a user is subscribed
š Fetching Weather Data
The naive choice might be to use Kinesis for streamingābut weāre just polling a single public API (Open-Meteo) every 5 minutes. Kinesis wouldāve added unnecessary complexity and cost.
Instead, we scheduled a Lambda using EventBridge to hit the API, parse the data, and store it as a raw JSON file in an S3 bucket.
š§© CDK Snippet:
new events.Rule(this, 'WeatherFetchRule', {
schedule: events.Schedule.rate(Duration.minutes(5)),
targets: [new targets.LambdaFunction(weatherFetcherLambda)],
});
š§¹ Processing Data with Glue
Now that we have raw JSON in S3, we transform it using AWS Glue. Our hourly Glue job:
- Reads raw JSON
- Converts it to partitioned Parquet
- Writes output to a processed S3 bucket
š§© CDK Snippet:
const glueJob = new glue.CfnJob(this, 'WeatherGlueJob', {
name: 'weather-transform-job',
role: glueJobRole.roleArn,
command: {
name: 'glueetl',
pythonVersion: '3',
scriptLocation: glueScriptAsset.s3ObjectUrl,
},
defaultArguments: {
'--enable-glue-datacatalog': 'true',
'--job-bookmark-option': 'job-bookmark-enable',
'--TempDir': `s3://${glueTempBucket.bucketName}/temp/`,
},
glueVersion: '4.0',
maxRetries: 1,
timeout: 10,
});
š Querying with Athena
Athena lets us query S3 like itās a database. With Parquet files and partitioned data, Athena becomes incredibly efficient. The Glue job creates a schema in Glue Catalog that Athena uses.
š§© CDK Snippet:
new glue.CfnDatabase(this, 'AthenaDatabase', {
catalogId: this.account,
databaseInput: { name: 'weather_data' },
});
š Visualizing with QuickSight
For dashboards, we connected Amazon QuickSight directly to Athena to display insights on:
- Temperature
- Precipitation
- Alerts
We configured QuickSight via console since embedding requires domain validation and dashboard sharing configuration.
š¢ Letās Send Some Alerts
We created two Lambda functions:
- Daily digest
- Severe weather alert
Each Lambda uses SES to send templated emails with unsubscribe links.
š§© CDK Snippet:
const dailyAlertLambda = new lambda.Function(this, 'DailyAlertLambda', {
runtime: lambda.Runtime.PYTHON_3_11,
handler: 'daily.handler',
code: lambda.Code.fromAsset(path.join(__dirname, '../lambda/daily-alert')),
environment: {
SENDER_EMAIL: senderEmail,
DDB_TABLE_NAME: table.tableName,
},
});
š Security & IAM
- IAM Roles for Lambda & Glue
- VPC endpoints for S3
- SES verification via CDK
š§© CDK Snippet:
new ses.EmailIdentity(this, 'EmailIdentity', {
identity: ses.Identity.email(senderEmail),
});
šļø Infrastructure with CDK + CI/CD
Everything is defined in CDK and deployed via GitHub Actions.
š§© GitHub Actions Sample:
- name: Deploy to AWS
run: |
npm ci
npm run build
npx cdk deploy --require-approval never
š Monitoring & Logging
We used CloudWatch for logging and metrics, with Lambda and Glue emitting events for errors or retries.
ā Wrapping It Up
With CDK and the AWS ecosystem, we built a fully serverless system togetherāfrom data ingestion to user communication. Clone the full code and start building your version of this:
š GitHub Repo
Happy coding! āļø
Leave a comment