DELIVERY INVESTIGATION GUIDE

BullMQ job completed,
but the webhook was not confirmed.

A completed job tells you about the processor. Investigate the HTTP request, PostgreSQL outbox, worker, and receiver evidence to understand a webhook’s outcome.

01 / THE SYMPTOM

The job is complete.
Is delivery confirmed?

A BullMQ job marked completed does not, by itself, prove that the webhook receiver committed a business effect. Completion has the meaning your processor gives it: inspect what it awaited, what it returned, and how it handled errors.

BullMQ moves a successfully processed job to its completed state; a processor can return a value that is exposed through the job and its completion event. See the official BullMQ worker documentation.

If a processor records a webhook timeout and then returns normally, the queue job can complete while delivery remains unknown. If work is started in a completion listener, that later work can fail after the job completed. BullMQ documents this distinction for result storage in Returning job data.

Likewise, an HTTP success response confirms only what the receiver’s response contract guarantees. An acknowledgement may precede further processing. Confirming an external effect requires explicit evidence from the system that owns that effect.

Separate three questions.

  • Did the worker finish its processor?
  • Was the webhook accepted, and was a response observed?
  • Was the intended receiver effect explicitly confirmed?

These answers can differ for the same execution.

02 / SYNTHETIC EVIDENCE

Accepted request.
Unknown outcome.

A read-only illustration of the packaged example’s webhook-unknown scenario. No account or live customer data is involved.

ILLUSTRATION · NOT A LIVE EXECUTION

Outcome unknown

Last confirmed boundary: Webhook request

The receiver accepted the request, but the worker’s deadline expired before a response was observed. No external-effect confirmation is present.

  1. HTTP request

    http.request / started

    The API received the synthetic operation.

  2. Database commit

    database.commit / succeeded

    The transaction containing the operation and outbox committed.

  3. Outbox write

    outbox.write / succeeded

    The application reported its outbox record after commit.

  4. Queue enqueue

    queue.enqueue / succeeded

    The relay observed the enqueue acknowledgement.

  5. Webhook request

    webhook.request / accepted

    The receiver accepted the request. This is the last positive confirmation in this illustration.

  6. Webhook response

    webhook.request / failed · WEBHOOK_TIMEOUT

    The worker did not observe a response within its deadline. The outcome remains unknown.

  7. External effect — not observed

    Display-only projection. No received event, source status, or timestamps.

This schematic omits timestamps and does not claim measured durations or receipt order. In the dashboard, source occurrence and collector receipt are separate times, and event ordering is deterministic.

The timeout event’s source status remains failed, with WEBHOOK_TIMEOUT. The dashboard may display response not observed for this observation. That does not turn the execution into a confirmed delivery failure.

In this controlled fixture, the receiver deliberately waits without committing an effect. The local test can inspect that database fact. The collected Evidence alone cannot establish absence of an effect in another system.

03 / INVESTIGATE

Find the last
confirmed boundary.

  1. Connect the same execution across processes.

    Follow the same opaque execution reference from the HTTP request into the transaction and durable outbox, then through the relay and worker. A nearby completed job or a recent collector receipt may belong to different work.

  2. Check the transaction and enqueue acknowledgements.

    An outbox row records intent to deliver. An enqueue acknowledgement confirms the queue accepted the job. Neither observation confirms webhook delivery. Emit commit evidence only after the transaction commits.

  3. Read the processor’s actual completion conditions.

    Check whether the webhook call is awaited, whether response status is checked, and whether timeout or network errors are caught and returned. Inspect application-owned records locally; do not send request bodies, raw URLs, or exception stacks to the evidence collector.

  4. Look for receiver-owned confirmation.

    Ask which observation demonstrates that the receiver committed the intended effect. In the example, the receiver emits external.effect / succeeded after its own database insert commits. A caller timeout does not undo an effect that may already have happened.

  5. Keep missing observations separate from explicit reports.

    A worker failure report, a response timeout, and a reported connector interruption support different conclusions. Missing evidence can also reflect delay, instrumentation loss, retention expiry, or unfinished work. It is not proof of failure or proof of connector interruption.

Evidence receivedSupported conclusion
Explicit external-effect successDelivery confirmed for the reported effect.
Explicit worker failureFailure reported by the worker. Inspect its boundary and attempt.
Webhook timeout, no effect confirmationOutcome unknown. The response was not observed in time.
Explicit connector interruption, no final outcomeEvidence interrupted. Business work may have continued.

These are separate simplified examples, not a precedence rule for conflicting reports. Always inspect the full execution evidence.

04 / REPRODUCE LOCALLY

Read the code.
Compare the outcomes.

The Node.js delivery example ships inside the version 0.3.0 SDK archive. It runs separate API, outbox relay, BullMQ worker, and receiver processes with PostgreSQL 16 and Redis 7.

After following the example’s setup, run npm run smoke. It submits four new synthetic operations and compares the receiver’s database effect and worker outcome with captured Evidence. No Nestarc account or production ingest key is required.

Open src/worker.mjs to see the timeout branch: it records unknown, emits the timeout observation, and returns. Open src/receiver.mjs to see where acceptance and effect confirmation are separate observations. The interrupted scenario also shows business work succeeding while downstream evidence is suppressed.

The example is a bounded investigation fixture. It does not implement a production outbox recovery policy, prove a customer’s integration, or make an unknown operation safe to retry. Nestarc remains read-only.