Lambda Event Source Filters: Drop Noise Before Paying for Invokes

Lambda Event Source Filters: Drop Noise Before Paying for Invokes

Most stream and queue consumers waste money invoking Lambda for events the handler ignores in the first five lines. Event source mapping filters push that predicate to AWS so you never pay the invoke — the unfair advantage when DynamoDB streams fan out every attribute change or SQS carries mixed message types.

⚡ TL;DR: Attach FilterCriteria on ESMs for DynamoDB Streams, Kinesis, SQS, and MSK. Prefer allowlists on event names / type fields. Keep filters small and testable; dual-write metrics for “matched vs dropped” via stream lag dashboards. Combine with idempotency patterns from Bedrock Agents Idempotent Tool Calls when filtered traffic still retries.

Filter at the mapping, not in the handler prologue

// GOOD: only MODIFY with status=PAID
await lambda.createEventSourceMapping({
  FunctionName: "fulfill-order",
  EventSourceArn: streamArn,
  StartingPosition: "LATEST",
  FilterCriteria: {
    Filters: [
      {
        Pattern: JSON.stringify({
          eventName: ["MODIFY"],
          dynamodb: {
            NewImage: {
              status: { S: ["PAID"] },
            },
          },
        }),
      },
    ],
  },
});

// BAD: invoke on everything, return early
export const handler = async (event: { Records: Array<{ eventName: string }> }) => {
  for (const r of event.Records) {
    if (r.eventName !== "MODIFY") continue; // you already paid for this invoke
  }
};

✅ Pattern matches DynamoDB typed images ({ "S": ["PAID"] }).
❌ Filtering only in code after a full batch invoke.

SQS multi-type topics (really: one queue, many producers)

{
  "body": {
    "type": ["OrderPaid", "OrderRefunded"]
  }
}
FilterCriteria: {
  Filters: [
    { Pattern: '{"body":{"type":["OrderPaid","OrderRefunded"]}}' },
  ],
},

If body is a JSON string, use the SQS filter semantics carefully — AWS matches on the message body structure when content-type is JSON. Validate with aws lambda create-event-source-mapping dry-runs in staging.

Operational pitfalls

Pitfall Symptom Fix
Wrong typed image path Silent drop of all events Integration test with real stream record
Over-narrow filter after schema change Lag grows, business stalls Schema contract tests
Multiple filters OR semantics misunderstood Unexpected invokes Document OR across Filters array
Relying on filters for authz Security bug Filters ≠ authorization
// Canary: emit a synthetic PAID modify and expect invoke metric +1 within 60s

Dropped events do not invoke — they also do not hit your DLQ. That is desired for noise, catastrophic for misconfigured filters. Alarm on business KPIs (orders fulfilled/min), not only Lambda errors.

Closing checklist

  • [ ] ESM FilterCriteria deployed as code (CDK/Terraform), not console clicks
  • [ ] Patterns use correct DynamoDB type wrappers
  • [ ] Staging test proves match and non-match cases
  • [ ] KPI alarms detect accidental total-drop
  • [ ] Handlers remain defensive (filters can lag schema)
  • [ ] Cost dashboard shows invoke drop after filter rollout

Related reading

Last updated on September 11, 2026


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply