Time Series Forecasting App - Amazon Chronos-2
Building a production forecasting application without the complexity of traditional ML model training and feature engineering.
The Problem
Time series forecasting traditionally requires:
- Extensive feature engineering
- Model training on historical data
- Hyperparameter tuning
- Ongoing model retraining as patterns change
For many use cases, this complexity isn’t justified. You just need reasonable forecasts without becoming a machine learning team.
The Solution
Built a forecasting application using Amazon’s Chronos-2 foundation model — a 120M parameter model that provides zero-shot probabilistic forecasting. It works on any time series without task-specific training.
The stack:
- Frontend: React 19 + Cloudscape Design System
- Backend: AWS Amplify Gen 2 (Cognito, AppSync, DynamoDB)
- ML: SageMaker endpoint running Chronos-2
How It Works
Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ FRONTEND │
│ React 19 + Cloudscape Design System │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AWS AMPLIFY GEN 2 │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Amplify │ │ Cognito │ │ AppSync │ │ DynamoDB │ │
│ │ Hosting │ │ Auth │ │ GraphQL │ │ Tables │ │
│ └─────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AWS LAMBDA │
│ chronos-forecast-handler (Node.js) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AMAZON SAGEMAKER │
│ Chronos-2 Real-time Inference Endpoint │
│ (ml.g5.xlarge GPU instance) │
└─────────────────────────────────────────────────────────────────────────────┘
Lambda → SageMaker Invocation
The Lambda function handles the AppSync GraphQL request and invokes SageMaker:
import { SageMakerRuntimeClient, InvokeEndpointCommand } from "@aws-sdk/client-sagemaker-runtime";
const sagemakerRuntime = new SageMakerRuntimeClient({ region: "eu-west-1" });
export async function generateForecast(routeId: string, historicalPrices: number[]) {
const payload = {
inputs: [{
item_id: routeId,
target: historicalPrices,
}],
parameters: {
prediction_length: 4,
output_type: "quantiles",
quantiles: ["0.1", "0.5", "0.9"] // Confidence intervals
}
};
const command = new InvokeEndpointCommand({
EndpointName: process.env.SAGEMAKER_ENDPOINT,
ContentType: "application/json",
Body: JSON.stringify(payload),
});
const response = await sagemakerRuntime.send(command);
return JSON.parse(new TextDecoder().decode(response.Body));
}
Amplify Gen 2 Schema
Define the GraphQL schema with custom queries:
// amplify/data/resource.ts
export const data = defineData({
schema: `
type Route @model @auth(rules: [{ allow: private }]) {
routeId: ID! @primaryKey
name: String!
historicalPrices: [Float!]!
}
type ForecastResult {
routeId: ID!
predictions: [PredictionPoint!]!
}
type PredictionPoint {
period: String!
p10: Float!
p50: Float!
p90: Float!
}
type Query {
generateForecast(routeId: ID!): ForecastResult
@function(name: "chronos-forecast")
@auth(rules: [{ allow: private }])
}
`,
});
Visualizing Probabilistic Forecasts
Display P10/P50/P90 confidence intervals with Recharts:
import { LineChart, Line, Area, XAxis, YAxis, Tooltip } from "recharts";
function ForecastChart({ data }) {
return (
<LineChart data={data}>
<XAxis dataKey="period" />
<YAxis tickFormatter={(v) => `$${v}`} />
{/* Confidence interval band */}
<Area dataKey="p90" stroke="none" fill="#e3f2fd" fillOpacity={0.5} />
<Area dataKey="p10" stroke="none" fill="#ffffff" />
{/* Median forecast line */}
<Line dataKey="p50" stroke="#1976d2" strokeWidth={2} dot={{ r: 4 }} />
<Tooltip
formatter={(value, name) => [
`$${value.toFixed(2)}`,
name === "p50" ? "Forecast" : name === "p10" ? "Lower bound" : "Upper bound"
]}
/>
</LineChart>
);
}
Accuracy Metrics
Track forecast quality:
// MAPE - Mean Absolute Percentage Error
function calculateMAPE(actual: number[], predicted: number[]): number {
const sumAbsPercentError = actual.reduce((sum, val, i) => {
if (val === 0) return sum;
return sum + Math.abs((val - predicted[i]) / val);
}, 0);
return (sumAbsPercentError / actual.length) * 100;
}
// Interval Coverage - % of actuals within P10-P90
function calculateCoverage(actual: number[], p10: number[], p90: number[]): number {
const withinInterval = actual.filter(
(val, i) => val >= p10[i] && val <= p90[i]
).length;
return (withinInterval / actual.length) * 100;
}
What I Learned
- Chronos-2 simplifies forecasting — No feature engineering or model training required
- Amplify Gen 2 accelerates full-stack development — Schema-driven backend with TypeScript
- Probabilistic forecasts are more useful — P10/P50/P90 enables risk-aware decisions instead of false precision
- Proper backtesting is essential — Walk-forward validation with actual model predictions, not just historical fit
Do It Yourself
Key Takeaways
- Foundation models eliminate training complexity — Chronos-2 provides zero-shot forecasting on any time series without custom training, feature engineering, or hyperparameter tuning.
- Probabilistic forecasts beat point estimates — P10/P50/P90 quantiles communicate uncertainty and enable risk-aware decision-making. Never trust a single forecast line without confidence intervals.
- Amplify Gen 2 speeds up full-stack ML apps — schema-driven backends with built-in auth, GraphQL API, and Lambda integrations cut weeks of boilerplate from ML application development.
Try It Now
- Deploy Chronos-2 to SageMaker — use the AWS Marketplace listing or deploy from HuggingFace. The
chronos-t5-base(120M parameters) runs onml.g5.xlarge. Deployment guide: Amazon Chronos on SageMaker - Call the model via SDK — invoke the endpoint with historical time series data in JSON format. Full payload schema: Chronos inference format
- Implement walk-forward backtesting — validate accuracy by progressively hiding recent data and measuring forecast error. Never test on training data. Example: scikit-learn TimeSeriesSplit
- Set up SageMaker Model Monitor — detect data drift and forecast quality degradation over time. Tutorial: SageMaker Model Monitor guide
- Build your UI with Amplify Gen 2 — scaffold a full-stack app with auth, API, and database in minutes. Starter template: AWS Amplify Gen 2 quickstart
ONE LETTER A MONTH · NO TRACKER · UNSUBSCRIBE ANYTIME
Comments
Sign in to leave a comment
