Scalable APIs for Distributed Generation with Node.js/TypeScript on AWS
Monitoring Distributed Generation (DG) solar power plants requires fast and reliable data ingestion. Photovoltaic inverters send generation logs every 5 or 15 minutes, generating a constant telemetry traffic that needs to be processed, stored, and utilized for billing energy balance.
In this article, I present the design of a resilient microservices architecture built with Node.js, TypeScript, and hosted on AWS, combining serverless processing with event-driven message buses.
Architecture Design
To ensure scalability with low operational costs, we implemented the following API topology:
- API Gateway: Public entry point for receiving JSON payloads sent by inverters.
- AWS SQS (Simple Queue Service): Immediate decoupling of requests to avoid bottlenecks during telemetry spikes.
- AWS Lambda (Serverless Node.js): Functions focused on parsing data payloads, validating electrical parameters, and storing consolidated data.
- AWS Aurora PostgreSQL: Structured final storage for quick reports and operational auditing.
Code Sample (TypeScript)
The TypeScript controller below showcases a clean structure for validating data using validation decorators and static typing:
import { Request, Response } from 'express';
export class InverterController {
async processTelemetry(req: Request, res: Response) {
const { inverterId, activePowerKwh, timestamp } = req.body;
// Asynchronous processing and queueing
console.log([INFO] Telemetria recebida do inversor ${inverterId});
return res.status(202).json({ status: 'queued' });
}
}
From the plant to the queue
The controller returns 202 and the work continues on SQS. Without the queue, an inverter spike at noon holds the API.
aws sqs send-message \
--queue-url "$QUEUE_URL" \
--message-body '{"inverterId":"INV-14","activePowerKwh":4.2,"timestamp":"2026-10-01T15:00:00Z"}'
On Lambda the same message is typed. If activePowerKwh is not a number, the function drops it onto the DLQ instead of writing junk into Aurora.
type Telemetry = {
inverterId: string;
activePowerKwh: number;
timestamp: string;
};
export function parseTelemetry(body: string): Telemetry {
const data = JSON.parse(body) as Telemetry;
if (typeof data.activePowerKwh !== "number") {
throw new Error("invalid activePowerKwh");
}
return data;
}
Benefits of TypeScript in Solar Engineering
The use of static typing prevents critical inconsistencies in complex mathematical calculations for energy allocation in solar energy cooperatives, ensuring a much cleaner code free of classic mathematical bugs from dynamic JavaScript.
Related Articles
Multi-cloud for Banks: Separating the Core, Data, and the Audit Trail
Multi-cloud architecture for banks: a locked region, a core isolated from the lab, and an audit trail nobody can delete. SCP, CloudTrail, and Object Lock commands.
SAP Business One with SAP HANA on AWS: Architecture and Day-to-Day Operations
How to run SAP Business One on SAP HANA on AWS: instance, data and log volumes, port 30015, and backup. Power BI reads the replica, not production HANA.