A fully automated serverless pipeline that tracks daily top movers from a watchlist of tech stocks. Built on AWS using CDK for infrastructure as code.
http://serverless-stocks-frontend-707714592503.s3-website-us-east-1.amazonaws.com/
- EventBridge triggers a Lambda function on a daily schedule
- Lambda (today-top) fetches open/close prices for each stock in the watchlist, calculates % change, and writes all results to DynamoDB with the top mover flagged
- DynamoDB stores daily stock data with
dateas partition key andtickeras sort key - Lambda (past-toppers) scans DynamoDB, groups by date, and returns the most recent 7 trading days via API Gateway
- API Gateway exposes a
GET /moversendpoint for the frontend - S3 (CDK-managed) hosts the static frontend
- CloudWatch + SNS monitors the ingestion lambda for errors and sends email alerts
- Secrets Manager stores the stock API key securely
AAPL MSFT GOOGL AMZN TSLA NVDA
- Node.js v20+
- AWS CLI configured (
aws configure) - AWS CDK installed (
npm install -g aws-cdk) - A free Massive account with an API key
git clone https://github.com/jinpas/serverless-stocks.git
cd serverless-stocks
npm installCreate a .env file:
MASSIVE_API_KEY=your_api_key_here
ALERT_EMAIL=your@email.com
Store your API key in AWS Secrets Manager:
aws secretsmanager create-secret \
--name "massive-api-key" \
--secret-string "your_api_key_here"Bootstrap CDK (one-time):
cdk bootstrapDeploy:
cdk deployPushing to main automatically:
- Deploys the CDK stack
- Uploads the frontend to the S3 website bucket
Required GitHub secrets:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYALERT_EMAIL
GET /movers
Returns the most recent 7 trading days, including all tracked stocks for each day with the top mover flagged.
[
{
"date": "2026-03-27",
"stocks": [
{
"ticker": "AAPL",
"percentChange": -2.01,
"closingPrice": 248.8,
"isTopMover": true
}
]
}
]End-of-day data timing
The data provider returns end-of-day aggregates that are not consistently available immediately after market close. To ensure reliability, the ingestion lambda queries the most recently completed trading day (typically yesterday) rather than the current in-progress day.
Rate limiting
The free tier of the Massive API allows 5 requests per minute. With 6 stocks, the ingestion lambda introduces a 15 second delay between requests and retries up to 3 times on errors. On a paid plan this delay would be removed.
DynamoDB scan
The retrieval Lambda reads all records from the table and then filters out the most recent 7 days in code. This works fine because the dataset is small, but for larger datasets it would be more efficient to query only the needed dates instead of reading everything.
Weekend and market closures
The API returns no data on weekends and holidays. These days are skipped in ingestion and rendered as "market closed" in the UI.
Frontend data model
The API returns all stocks for each day (not just the top mover) with an isTopMover flag. This allows the UI to highlight the top mover while still letting users inspect the full watchlist.
- Remove rate limit delays on a paid API plan
- Split CDK stack into modular constructs
- Add CloudWatch dashboards for latency, success rate, and execution time
- Move frontend deployment fully into CDK (instead of CLI upload)