Cloud Cost Optimization

How to Set Up AWS Cost Anomaly Detection in 30 Minutes (with Lambda Code)

7 min read

AWS Cost Anomaly Detection is one of the most under-deployed features in AWS. It is free, takes 30 minutes to wire up, and routinely catches misconfigurations that would otherwise burn $5,000 before anyone notices.

This post walks through the full setup, plus a Lambda function that posts anomalies to Slack with rich formatting.

Step-by-step Workflow

  1. 01Enable Cost Anomaly Detection (Cost Explorer)

    Console → Billing → Cost Anomaly Detection. Create a monitor for “AWS services” at the account level.

  2. 02Create an SNS topic for anomaly events

    One topic per environment. We use finops-anomalies-prod and finops-anomalies-dev.

  3. 03Subscribe a Lambda function to the SNS topic

    The Lambda transforms AWS’s JSON payload into a Slack-friendly Block Kit message.

  4. 04Configure threshold and Slack channel routing

    $50 minimum impact for dev, $500 for prod. Different Slack channels per severity.

  5. 05Test with the AWS-provided sample event

    Console → Lambda → Test → use the SNS sample template; verify the Slack message renders.

5-Lever FinOps FrameworkFrom audit to optimization — week-by-week01RightsizingEC2 + RDSnWeek 1–202CommitmentsSavings PlansnWeek 303Idle AuditEBS, EIPs, NATnWeek 3–404Data TransferVPC EndpointsnWeek 5–705Cost AllocationPer-customernWeek 8–10Result: 38% cost reduction · $420K annualized savings · 99.97% uptimeReal engagement · B2B SaaS · 90 days
The 5-lever framework Ohveda used to cut a B2B SaaS client’s AWS bill by 38% in 90 days.

The Lambda Function (Python 3.12)

import json
import os
import urllib.request

SLACK_WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"]


def lambda_handler(event, context):
    """Forward AWS Cost Anomaly Detection events to Slack."""
    for record in event.get("Records", []):
        anomaly = json.loads(record["Sns"]["Message"])

        impact = anomaly.get("impact", {})
        total = impact.get("totalImpact", 0)
        service = anomaly.get("anomalyDetails", {}).get("service", "Unknown")

        message = {
            "text": f":rotating_light: AWS cost anomaly: ${total:.2f} on {service}",
            "blocks": [
                {
                    "type": "header",
                    "text": {"type": "plain_text", "text": ":money_with_wings: Cost Anomaly Detected"},
                },
                {
                    "type": "section",
                    "fields": [
                        {"type": "mrkdwn", "text": f"*Service:*n{service}"},
                        {"type": "mrkdwn", "text": f"*Impact:*n${total:,.2f}"},
                        {"type": "mrkdwn", "text": f"*Account:*n{anomaly.get('accountId', '-')}"},
                        {"type": "mrkdwn", "text": f"*Region:*n{anomaly.get('region', '-')}"},
                    ],
                },
                {
                    "type": "actions",
                    "elements": [
                        {
                            "type": "button",
                            "text": {"type": "plain_text", "text": "Open in Cost Explorer"},
                            "url": "https://console.aws.amazon.com/cost-management/home#/anomaly-detection",
                        }
                    ],
                },
            ],
        }

        req = urllib.request.Request(
            SLACK_WEBHOOK_URL,
            data=json.dumps(message).encode("utf-8"),
            headers={"Content-Type": "application/json"},
        )
        urllib.request.urlopen(req, timeout=5)

    return {"statusCode": 200}

The IAM Policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
  ]
}

What to Watch For

  • S3 PUT spikes from a misconfigured CI job
  • NAT Gateway data transfer surprises (cross-AZ chatty workloads)
  • CloudWatch Logs ingestion explosions (forgotten DEBUG level)
  • EC2 instance type drift after a Karpenter config change

Ready to optimize your cloud or AI footprint?

Book a free 30-minute architecture review. We will deliver a written cost-and-architecture audit within 48 hours.

Book a free architecture review · sales@ohveda.com

Need help with AWS cost anomaly detection?

Ohveda runs free 30-minute architecture reviews. We will identify your top opportunities in writing within 48 hours — at no cost.

Book a Free Architecture Review →