DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor AWS Lambda Functions with Vigilmon

How to Monitor AWS Lambda Functions with Vigilmon

AWS Lambda functions are invisible by default. They execute in response to events, leave no persistent processes to watch, and fail in ways that don't surface until downstream systems start breaking. Cold starts add latency spikes. Concurrency limits cause silent throttling. Memory limits trigger silent OOM kills.

This guide covers how to monitor Lambda functions using Vigilmon — both through Lambda URLs/API Gateway endpoints and through custom synthetic health checks.

The Challenge of Serverless Monitoring

Lambda monitoring is fundamentally different from monitoring a running server:

  • No persistent process to check TCP connections on
  • Cold starts cause response time spikes that look like outages
  • Silent throttling — Lambda returns 429 when concurrency limits hit, often without alerting anyone
  • Regional failures — Lambda in one AWS region can fail while others work fine
  • Downstream cascades — a Lambda failure in an event-driven architecture silently breaks other services

Approach 1: Monitor via Lambda Function URLs

Lambda Function URLs (introduced 2022) give your Lambda a permanent HTTPS endpoint. This is the cleanest way to monitor Lambda with Vigilmon.

Create a Health Check Lambda

// health-check/index.mjs
export const handler = async (event) => {
  const checks = {};
  let healthy = true;

  // Check DynamoDB connectivity
  try {
    const { DynamoDBClient, DescribeTableCommand } = await import('@aws-sdk/client-dynamodb');
    const client = new DynamoDBClient({ region: process.env.AWS_REGION });
    await client.send(new DescribeTableCommand({ TableName: process.env.TABLE_NAME }));
    checks.dynamodb = 'ok';
  } catch (err) {
    checks.dynamodb = `error: ${err.message}`;
    healthy = false;
  }

  // Check SQS queue accessibility
  try {
    const { SQSClient, GetQueueAttributesCommand } = await import('@aws-sdk/client-sqs');
    const client = new SQSClient({ region: process.env.AWS_REGION });
    await client.send(new GetQueueAttributesCommand({
      QueueUrl: process.env.QUEUE_URL,
      AttributeNames: ['ApproximateNumberOfMessages']
    }));
    checks.sqs = 'ok';
  } catch (err) {
    checks.sqs = `error: ${err.message}`;
    healthy = false;
  }

  return {
    statusCode: healthy ? 200 : 503,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      status: healthy ? 'ok' : 'degraded',
      timestamp: new Date().toISOString(),
      checks
    })
  };
};
Enter fullscreen mode Exit fullscreen mode

Deploy with Function URL

# Create the Lambda function
aws lambda create-function \
  --function-name vigilmon-health-check \
  --runtime nodejs20.x \
  --role arn:aws:iam::YOUR_ACCOUNT:role/lambda-health-role \
  --handler index.handler \
  --zip-file fileb://health-check.zip

# Add a Function URL with no auth (public health endpoint)
aws lambda create-function-url-config \
  --function-name vigilmon-health-check \
  --auth-type NONE
Enter fullscreen mode Exit fullscreen mode

This gives you a URL like:
https://abc123.lambda-url.us-east-1.on.aws/

Point Vigilmon at this URL.

Approach 2: Monitor via API Gateway

If your Lambda runs behind API Gateway:

// app.js (with aws-serverless-express or similar)
const express = require('express');
const app = express();

app.get('/health', (req, res) => {
  // Check Lambda memory usage
  const memUsed = process.memoryUsage();
  const checks = {
    process: 'ok',
    memory_mb: Math.round(memUsed.heapUsed / 1024 / 1024)
  };

  res.json({ status: 'ok', lambda: 'healthy', ...checks });
});
Enter fullscreen mode Exit fullscreen mode

Monitor https://api.yourdomain.com/health in Vigilmon.

Approach 3: CloudWatch → Vigilmon Webhook

For Lambda functions not exposed via HTTP, route CloudWatch alarms to Vigilmon via webhook:

  1. Create CloudWatch alarm for Lambda errors:
aws cloudwatch put-metric-alarm \
  --alarm-name my-lambda-errors \
  --namespace AWS/Lambda \
  --metric-name Errors \
  --dimensions Name=FunctionName,Value=my-function \
  --statistic Sum \
  --period 60 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --evaluation-periods 1
Enter fullscreen mode Exit fullscreen mode
  1. Route the alarm to an SNS topic → Lambda → Vigilmon webhook

Critical Lambda Metrics to Monitor

Metric What it means Alert threshold
Errors Function threw an exception >0 per minute
Throttles Concurrency limit hit >0 per minute
Duration Execution time >80% of timeout
ConcurrentExecutions Simultaneous invocations >80% of reserved concurrency
IteratorAge SQS/Kinesis event lag >30 seconds

Vigilmon Configuration for Lambda

  1. Sign up at vigilmon.online
  2. Add HTTP Monitor → your Lambda URL or API Gateway health endpoint
  3. Check interval: 1 minute
  4. Expected status: 200
  5. Response time alert: 5000ms (account for cold start latency)
  6. Multi-region: Vigilmon checks from multiple AWS regions — this is critical for Lambda since region-specific failures are common

Handling Cold Starts in Monitoring

Lambda cold starts can take 500ms-3000ms. To avoid false alerts:

  1. Set Vigilmon's response time alert at 5000ms (not 1000ms)
  2. Use Lambda Provisioned Concurrency for critical functions to eliminate cold starts
  3. Configure Vigilmon's alert policy to require 2 consecutive failures before alerting

Synthetic Monitoring for Event-Driven Lambdas

For Lambdas triggered by SQS/EventBridge (not directly by HTTP), create a synthetic test:

// synthetic-health-check/index.mjs
import { SQSClient, SendMessageCommand, ReceiveMessageCommand, DeleteMessageCommand } from '@aws-sdk/client-sqs';

export const handler = async () => {
  const sqs = new SQSClient({ region: process.env.AWS_REGION });
  const testId = `health-${Date.now()}`;

  // Send a test message to trigger the Lambda
  await sqs.send(new SendMessageCommand({
    QueueUrl: process.env.TEST_QUEUE_URL,
    MessageBody: JSON.stringify({ type: 'health_check', id: testId }),
    MessageAttributes: { 'test': { DataType: 'String', StringValue: 'true' } }
  }));

  // Wait 10 seconds and check DynamoDB for the processed result
  await new Promise(r => setTimeout(r, 10000));

  // Verify processing completed
  // ... check DynamoDB for the testId ...

  return { statusCode: 200, body: 'ok' };
};
Enter fullscreen mode Exit fullscreen mode

Run this synthetic check on a schedule (EventBridge rule) and expose its result via a health endpoint.

Production Checklist

  • [ ] Lambda Function URL or API Gateway health endpoint created
  • [ ] Health check verifies downstream dependencies (DynamoDB, SQS, etc.)
  • [ ] Vigilmon HTTP monitor pointed at the health endpoint
  • [ ] Response time alert at 5000ms (cold start tolerance)
  • [ ] CloudWatch alarm for Lambda Errors and Throttles
  • [ ] Alert 2+ consecutive failures before paging on-call
  • [ ] Synthetic health check for event-driven Lambdas

Start monitoring your Lambda functions for free →


Vigilmon is an uptime monitoring platform for developers. Free tier includes 10 monitors with 1-minute checks from multiple global regions.

Top comments (0)