Updating data status with API Gateway WebSocket API
Source: Dev.to
TL;DR
Amazon API Gateway’s WebSocket API can keep the front‑end up to date with the latest data, providing a near‑real‑time alternative to polling a REST API endpoint for status notifications.
The scenario
Suppose we operate a click‑data processing application. Customers interact with links and buttons on our page, and the application records the number and type of clicks. An authorized, browser‑based dashboard displays the current click counts. The front‑end only presents data—no business logic.
Click results are persisted in a database and retrieved by the client from the backend. The question is how to display the current click‑count status in near real‑time.
Requirements
- The dashboard should display clicks in real or near‑real time.
- Minimize human interaction; the solution should be as automated as possible.
- Click results must be persisted in a database.
- The solution should scale.
- Architecture must be extendable and its elements reusable for other business scenarios.
- Infrastructure must be hosted on AWS and be serverless.
Options
| Approach | Pros | Cons |
|---|---|---|
| Polling | Simple to implement; works with existing REST APIs. | Expensive at scale; adds latency; requires poller management (intervals, cleanup). |
| WebSockets | Push‑based, near‑real‑time updates; reduces network traffic; no poller logic needed. | Requires WebSocket API setup and connection‑ID management. |
Testing showed polling to be reasonable but costly, prompting the WebSocket approach.
Architecture overview
The diagram is omitted for brevity.
The architecture consists of:
- Ingestion –
/ingestREST endpoint (API Gateway) →IngestClickDataLambda → DynamoDB table. - WebSocket API –
$connect,$disconnect,$defaultroutes. - Connection‑ID persistence –
PersistConnectionIdsLambda stores connection IDs in DynamoDB. - Stream processing – DynamoDB Streams trigger
StreamProcessorLambda, which broadcasts click updates to all connected clients. - Dashboard client – Connects to the WebSocket API and receives real‑time click status messages.
Pre‑requisites
- An AWS account with permission to create API Gateway (REST & WebSocket), Lambda, DynamoDB, and DynamoDB Streams.
- Familiarity with infrastructure‑as‑code tools (e.g., AWS CDK) is helpful but not required.
Implementation details
Ingestion
When a user clicks an element, the front‑end sends click data to the /ingest REST endpoint. IngestClickData Lambda validates (and optionally transforms) the payload and writes it to DynamoDB with a PutItem operation.
Note: If no validation/transformation is needed, API Gateway can write directly to DynamoDB, eliminating the Lambda and saving a few dozen milliseconds.
Dashboard connection (WebSocket client)
// connectWebSocket.js
function connectWebSocket() {
// 1. Create the WebSocket object
const ws = new WebSocket(WEBSOCKET_URL);
// 2. Connection opened
ws.onopen = () => {
updateConnectionStatus(ConnectionStatus.CONNECTED);
};
// 3. Message received
ws.onmessage = handleMessage;
// 4. Connection closed
ws.onclose = (event) => {
updateConnectionStatus(ConnectionStatus.DISCONNECTED);
// Optional reconnection logic here
};
// 5. Error occurred
ws.onerror = (error) => {
updateConnectionStatus(ConnectionStatus.DISCONNECTED);
// onerror is always followed by onclose
};
}
WEBSOCKET_URL follows the same pattern as REST APIs, e.g.:
wss://.execute-api.eu-central-1.amazonaws.com//
When using IaC (e.g., CDK), the URL can be injected into the client bundle at build time.
WebSocket routes
- $connect – Triggers
PersistConnectionIdsLambda, which stores the generated connection ID in DynamoDB. - $disconnect – Triggers
DeleteConnectionIdsLambda, which removes the connection ID when a dashboard client leaves. - $default – Not used in this example; serves as a fallback.
DynamoDB Streams & StreamProcessor
IngestClickData writes new click records to DynamoDB, generating a Streams event. StreamProcessor Lambda consumes these events, filters for click‑data items, and broadcasts the updated status to all stored connection IDs via the WebSocket API.
If click data and connection IDs share a single table, an event filter can reduce unnecessary invocations:
// CDK example – filter for items where entityType = 'CLICK'
streamProcessorLambda.addEventSource(
new lambdaEventSources.DynamoEventSource(clickstreamTable, {
// ... other properties
filters: [
lambda.FilterCriteria.filter({
dynamodb: {
NewImage: {
entityType: {
S: lambda.FilterRule.isEqual('CLICK')
}
}
}
})
]
})
);
Broadcasting click data
The StreamProcessor retrieves all active connection IDs from DynamoDB and uses the API Gateway Management API to post a message to each client:
// Pseudo‑code
for (const connId of connectionIds) {
await apigatewaymanagementapi.postToConnection({
ConnectionId: connId,
Data: JSON.stringify(clickStatus)
}).promise();
}
Receiving click results (client side)
handleMessage parses the incoming payload and updates the UI (e.g., incrementing a counter or refreshing a chart).
function handleMessage(event) {
const data = JSON.parse(event.data);
// Update UI with the new click count
updateClickCount(data.count);
}
Discussion points
No need for a REST API?
If the ingestion path never requires validation, you can bypass the REST API and have API Gateway write directly to DynamoDB, further reducing latency and cost.
Asynchronous workflows
The architecture naturally supports asynchronous processing: click events are stored, streamed, and broadcast without blocking the client.
Flexibility
- Separate tables – Click data and connection IDs can be stored in distinct tables for clearer separation of concerns.
- Additional consumers – Other services can subscribe to the same DynamoDB Stream (e.g., analytics, alerting).
- Scaling – Lambda concurrency and DynamoDB provisioned capacity can be adjusted automatically.
Summary
By combining a REST ingestion endpoint, DynamoDB Streams, and an API Gateway WebSocket API, we achieve near‑real‑time dashboard updates without the overhead of client‑side polling. The solution is fully serverless, scalable, and reusable across different business scenarios.