Scalable APIs for Distributed Generation with Node.js/TypeScript on AWS

May 28, 20266 min read
"Node.js""TypeScript""AWS""Serverless"

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:

  1. API Gateway: Public entry point for receiving JSON payloads sent by inverters.
  2. AWS SQS (Simple Queue Service): Immediate decoupling of requests to avoid bottlenecks during telemetry spikes.
  3. AWS Lambda (Serverless Node.js): Functions focused on parsing data payloads, validating electrical parameters, and storing consolidated data.
  4. 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