Skip to content

[codex] Fix idle SQS polling in development#1

Merged
manynames3 merged 1 commit into
mainfrom
codex/fix-sqs-idle-polling
Jun 19, 2026
Merged

[codex] Fix idle SQS polling in development#1
manynames3 merged 1 commit into
mainfrom
codex/fix-sqs-idle-polling

Conversation

@manynames3

Copy link
Copy Markdown
Owner

Summary

  • configure 20-second long polling on every Terraform-managed SQS queue
  • disable Lambda SQS event-source mappings by default in dev/local environments while preserving production defaults
  • align source-queue visibility timeouts with Lambda execution limits
  • add worker batch observability, Terraform regression tests, CI coverage, and an operations runbook
  • refresh vulnerable existing development dependency resolutions required by the repository audit gate

Root cause

The application has no direct ReceiveMessage loop. Terraform created always-enabled Lambda SQS event-source mappings, so the Lambda service continuously polled empty development queues. The observed rate of roughly 8,640 empty receives per day matches that managed poller behavior.

Lambda does not invoke handlers for empty receives, so application-side exponential backoff cannot run here. Disabling dev mappings is the stronger idle control: it stops receives entirely until enable_sqs_workers=true is set intentionally.

Behavior

  • dev, development, and local: mappings default disabled
  • production and other environments: mappings remain enabled by default
  • successful records retain partial-batch deletion semantics; failed records are not deleted
  • existing 1/5/1 batch sizes remain because workers make sequential external calls within bounded Lambda timeouts

Validation

  • npm run build
  • npm test (16 tests)
  • npm audit --audit-level=high (0 vulnerabilities)
  • npm run bundle
  • terraform fmt -check -recursive .
  • terraform validate
  • terraform test (3 tests)
  • git diff --check

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a mechanism to disable SQS Lambda event-source mappings by default in development environments to prevent idle polling costs, while allowing them to be explicitly enabled via a new Terraform variable. It also configures 20-second long polling across all SQS queues, updates visibility timeouts, adds detailed batch-start logging to the Lambda handlers, and introduces a suite of Terraform tests to validate these behaviors. The review feedback highlights a potential runtime vulnerability in the SQS handlers (deliver-webhook, enrich-transcript, and start-transcription) where event.Records is accessed without verifying if it is defined or non-empty, and suggests adding early guard clauses to prevent potential TypeError exceptions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +11 to +17
logInfo("sqs_worker_batch_started", {
worker: "deliver-webhook",
queueArn: event.Records[0]?.eventSourceARN,
batchSize: event.Records.length,
queueReceiveWaitTimeSeconds: 20,
idleBackoff: "managed-by-lambda-event-source-mapping"
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The handler currently accesses event.Records.length and event.Records[0] without verifying if event or event.Records is defined and non-empty. If the handler is invoked with an empty or malformed event payload (e.g., during manual testing or direct invocation), this will throw a runtime TypeError. Adding an early guard clause to validate the presence of records improves robustness and allows safe access to event.Records[0] without optional chaining.

  if (!event?.Records || event.Records.length === 0) {
    logWarn("sqs_worker_empty_or_invalid_event", { event });
    return { batchItemFailures: [] };
  }

  logInfo("sqs_worker_batch_started", {
    worker: "deliver-webhook",
    queueArn: event.Records[0].eventSourceARN,
    batchSize: event.Records.length,
    queueReceiveWaitTimeSeconds: 20,
    idleBackoff: "managed-by-lambda-event-source-mapping"
  });

Comment on lines +15 to +21
logInfo("sqs_worker_batch_started", {
worker: "enrich-transcript",
queueArn: event.Records[0]?.eventSourceARN,
batchSize: event.Records.length,
queueReceiveWaitTimeSeconds: 20,
idleBackoff: "managed-by-lambda-event-source-mapping"
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The handler currently accesses event.Records.length and event.Records[0] without verifying if event or event.Records is defined and non-empty. If the handler is invoked with an empty or malformed event payload (e.g., during manual testing or direct invocation), this will throw a runtime TypeError. Adding an early guard clause to validate the presence of records improves robustness and allows safe access to event.Records[0] without optional chaining.

  if (!event?.Records || event.Records.length === 0) {
    logWarn("sqs_worker_empty_or_invalid_event", { event });
    return { batchItemFailures: [] };
  }

  logInfo("sqs_worker_batch_started", {
    worker: "enrich-transcript",
    queueArn: event.Records[0].eventSourceARN,
    batchSize: event.Records.length,
    queueReceiveWaitTimeSeconds: 20,
    idleBackoff: "managed-by-lambda-event-source-mapping"
  });

Comment on lines +20 to +26
logInfo("sqs_worker_batch_started", {
worker: "start-transcription",
queueArn: event.Records[0]?.eventSourceARN,
batchSize: event.Records.length,
queueReceiveWaitTimeSeconds: 20,
idleBackoff: "managed-by-lambda-event-source-mapping"
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The handler currently accesses event.Records.length and event.Records[0] without verifying if event or event.Records is defined and non-empty. If the handler is invoked with an empty or malformed event payload (e.g., during manual testing or direct invocation), this will throw a runtime TypeError. Adding an early guard clause to validate the presence of records improves robustness and allows safe access to event.Records[0] without optional chaining.

  if (!event?.Records || event.Records.length === 0) {
    logWarn("sqs_worker_empty_or_invalid_event", { event });
    return { batchItemFailures: [] };
  }

  logInfo("sqs_worker_batch_started", {
    worker: "start-transcription",
    queueArn: event.Records[0].eventSourceARN,
    batchSize: event.Records.length,
    queueReceiveWaitTimeSeconds: 20,
    idleBackoff: "managed-by-lambda-event-source-mapping"
  });

@manynames3 manynames3 merged commit 581e640 into main Jun 19, 2026
6 of 7 checks passed
@manynames3 manynames3 deleted the codex/fix-sqs-idle-polling branch June 19, 2026 23:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant