ADR-0006: Delete dead EC2 background processors
- Status: accepted
- Date: 2026-04-17
Context
PropFlow's Next.js server (EC2 / PM2) starts a handful of setInterval
background processors at boot time via src/instrumentation.ts. Over the
course of 2025-2026 several of them have become redundant:
| Processor | File | Why it exists | Why it's dead |
|---|---|---|---|
| Email Replay | src/lib/email/replay-stalled.ts |
Resurrect email ingestion records stuck in processing/received after a server crash. |
SQS FIFO redrive + propflow-inbound.fifo DLQ now handle retries transparently. The processor only runs when SQS_INBOUND_QUEUE_URL is unset — which prod hasn't done since Phase 2. |
| Dead Letter Retry | src/lib/email/retry-processor.ts |
Periodically retry outbound emails that SendGrid/SES rejected with a transient error. | SendGrid's native retry + SES bounce handler cover every real-world case. The DL table has not had a successful resend in weeks. |
| Sync Digest | src/lib/rent-roll/sync-digest-processor.ts |
Fire a daily 8 AM CT digest email summarizing rent-roll sync activity. | Replaced by an ad-hoc admin trigger POST /api/admin/sync-digest + the daily cron described in scripts/. Nobody reads the auto-sent digest. |
| Voice Trace | src/lib/voice/voice-trace-processor.ts |
Backfill AgentTrace rows from ElevenLabs 20 s after each call, because ElevenLabs finalises analysis after the webhook fires. |
The voice call-ended webhook now builds the trace inline from the same payload (analysis arrives in the webhook body; the 20 s race is gone). |
In addition, two processors ARE still producing value, but the timer-on-EC2 shape is the wrong primitive for them:
| Processor | File | Better shape |
|---|---|---|
| Application Link | src/lib/leasing/application-link-processor.ts |
EventBridge Scheduler one-shot: tour confirmation schedules an invocation for now + postTourFollowUpDelayMinutes. |
| Listings Sync | src/lib/leasing/listings-sync-processor.ts |
EventBridge rate(15 m) rule targeting a tiny Lambda. |
Decision
- Delete the four dead processors (file + tests + comments). Their DynamoDB artefacts (e.g. dead-letter table entries, voice trace status flags) are left in place — no prod data is touched by this ADR.
- Migrate application-link to a one-shot
EventBridge Scheduler+ Lambda (propflow-application-link). Call site:applyTourIntent(action=confirmand auto-confirmedpropose). - Migrate listings-sync to an EventBridge rate(15m) rule + Lambda
(
propflow-listings-sync). - Until the new Lambdas have been live for one week, the existing
setInterval versions of application-link and listings-sync stay running
as a belt-and-braces safety net. After the cutover week, delete the
*-processor.tsfiles and thestartX()calls insrc/instrumentation.ts. - All prod AWS resource creation (EventBridge rules, Scheduler schedules,
IAM policies) is performed out-of-band via the deploy scripts checked
in under
lambda/<name>/deploy.sh. This ADR does not create any cloud resources on its own.
Consequences
src/instrumentation.tsshrinks from sevensetIntervalprocessors to two (both listed as "safety net — delete after cutover") plus the SQS inbound consumer.EmailIngestionRecord.processingStartedAt,replayCount, andlastReplayAtare retained in the schema for back-compat with records written before this change; new records only populateprocessingStartedAt(set bysrc/lib/email/process-inbound-email.ts).- Voice traces are built synchronously at call-ended time and visible on the admin trace page with no ~30 s lag.
- Tour-confirmation code paths now have an outbound side effect (an
EventBridge Scheduler
CreateSchedulecall). Failure to schedule is logged + swallowed — the setInterval safety-net still catches it.
Implementation notes
- Phase 5 worktree:
fede/phase5-processors. - Follow-up: when the cutover completes, a
refactor: remove legacy application-link + listings-sync setIntervalsPR will deletesrc/lib/leasing/application-link-processor.ts+src/lib/leasing/listings-sync-processor.tsand the corresponding imports fromsrc/instrumentation.ts. Seedocs/data-model-migration/architecture/phase5-cleanup-notes.md.