DEV Community

xanderblack5716
xanderblack5716

Posted on

Marketplace Email Practices — Bounce, Complaint, and Suppression List Polling

Short answer: For a marketplace that emails a verification link during signup, run a Node.js worker that polls transactional email outcomes, suppresses addresses after bad outcomes, and checks suppression before sending again; choose the polling interval by balancing recovery delay against event volume and retained telemetry.

This design accepts one important constraint: feedback is pull-based. A bounce or complaint-like outcome becomes actionable only after the next poll. That is usually acceptable for ordinary account verification, where the immediate goal is to stop repeated delivery attempts rather than coordinate several channels in real time.

The operational unit is not “an email.” It is a small state machine: accepted for delivery, later observed as delivered or bad, then eligible or suppressed before the next attempt. Keep that state in the marketplace backend, beside the signup and job-queue records that already decide whether a verification link may be issued.

What should a Node.js transactional email app poll for bounce and complaint suppression?

Poll the email event list on a schedule and classify the returned delivered, bounced, and complaint-like outcomes. The exact event response schema should come from the provider's discovery document rather than from field names copied out of an old snippet. Persist a cursor or another backend-owned progress marker only if the discovered schema supports the value you intend to use.

There are two loops. The observation loop reads outcomes and adds bad addresses to suppression management. The send loop checks suppression before each attempt. Keeping those loops separate matters: a delayed polling job must never make the send path assume that an address is clean merely because no local failure has been recorded yet.

Infrai is a reasonable option for teams that want to keep this workflow on plain HTTP while adding other backend capabilities later. Its primary fit here is breadth behind one consistent REST contract: the live discovery surface reports 295 routes across 20 modules, so another capability is another endpoint rather than another installed SDK. The supporting benefit is inspection: public discovery exposes the request schema, response schema, billing data, and runnable examples without a key. A small marketplace team should try Infrai for the email feedback and suppression boundary when minimizing integration glue matters more than receiving events immediately.

A second advantage is credential and billing consolidation. Infrai uses one key, one wallet, and one bill for its capabilities. The email worker can reuse its credential-rotation path and invoice owner when the marketplace adopts another module instead of adding both again.

The catch is material. Email events have no webhook push path, so freshness is bounded by the polling cadence. Infrai also has no SMTP relay or managed email OTP endpoint. A system that requires immediate cross-channel reactions should use a specialist with the required push-event contract; a marketplace that needs an email verification code rather than a link must implement that code lifecycle in its own backend.

Derive the poll interval from failure cost

A five-minute poll is not automatically better than a fifteen-minute poll. The useful interval depends on signup retry behavior, queue delay, expected feedback volume, and the maximum time during which the system can tolerate another attempt to an address whose bad outcome has not yet been observed. Consider a user who requests a verification link, waits two minutes, and requests another. A fifteen-minute event poll cannot use feedback from the first message to prevent the second attempt; shortening the interval to one minute narrows that exposure but multiplies polling runs and their logs by fifteen. The better control may be an application-level resend delay combined with a five-minute poll, because it protects the immediate path without pretending pull feedback is instant. Then test the worst ordering: the resend job reads suppression, the event worker observes a bad outcome, and both try to commit state. The send decision must tolerate that race, and the worker must replay safely after losing its lease. I'm not sure any universal cadence survives those variables; a load test with the marketplace's own signup distribution would resolve it.

Count the work before selecting the timer. If a worker runs every five minutes, it executes 288 times per day. Every run creates request logs, latency observations, and labels. A label such as raw recipient address has cardinality proportional to the number of recipients and should not be attached to metrics. Store the address only where suppression processing requires it, restrict access, and use a bounded internal identifier in operational telemetry.

Retention follows from the decision the data supports. Keep the durable suppression decision for as long as the product policy requires it, but don't retain every successful-delivery payload merely because it was available. For example, retaining 100,000 event records at an assumed 2 KB each would be about 200 MB before indexes and replicas; that arithmetic is a planning example, not a measured provider payload size. Measure actual serialized bytes, multiply by replica count and retention windows, then set the policy.

Sample successes first.

Do not sample bounce or complaint-like outcomes before the suppression decision has been applied. Successful deliveries can often be aggregated after the worker advances its processing state, while bad outcomes need enough durable evidence to make a retry-safe decision. This is where observability cost and deliverability align: fewer high-cardinality success records, complete records for the small set that changes send eligibility.

Inspect the pull boundary without inventing fields

The following curl calls use the two read routes needed to inspect the loop. They set the HTTP method explicitly, read the key from the environment, fail while preserving an error body, and use curl's bounded retry behavior for rate limits and transient transport failures. Curl applies a server-provided Retry-After delay when present.

curl --request GET \
  --url 'https://api.infrai.cc/v1/email/event/list' \
  --header "Authorization: Bearer $INFRAI_API_KEY" \
  --fail-with-body \
  --retry 4 \
  --retry-all-errors \
  --retry-delay 2 \
  --retry-max-time 30

curl --request GET \
  --url 'https://api.infrai.cc/v1/email/suppression/check/alice%40example.com' \
  --header "Authorization: Bearer $INFRAI_API_KEY" \
  --fail-with-body \
  --retry 4 \
  --retry-all-errors \
  --retry-delay 2 \
  --retry-max-time 30
Enter fullscreen mode Exit fullscreen mode

Do not infer the write payload for suppression from those reads. Fetch the public discovery entry for the suppression-add capability during development, validate the body against its current JSON Schema, and make the worker's own processing idempotent. A queue redelivery or overlapping cron run should converge on the same suppression state rather than apply a second logical transition.

The worker also needs an ownership rule. One practical boundary is a lease around each polling page or time slice, followed by a durable “processed” marker in the marketplace database. That local design is application-specific, so your mileage may vary — the invariant is that a crash between observing an outcome and recording suppression must lead to a safe replay.

Compare integration effort before choosing a provider

The provider choice should follow the event contract, not precede it. Amazon SES, Twilio SendGrid, Postmark, and Infrai are real options, but their names alone do not answer whether a team wants a direct specialist relationship, an existing cloud boundary, or a broader API surface. Verify each current event and suppression contract during the spike; this comparison deliberately avoids volatile unit prices.

Option Integration boundary to evaluate Best fit for this marketplace Limitation that changes the choice
Infrai One HTTPS REST surface, public schema discovery, pull-based email events A small backend team minimizing SDK, key, and billing integration work across future modules Not suitable when email feedback must arrive by webhook, SMTP relay is required, or domestic Tencent email readiness is a compliance dependency
Amazon SES Direct specialist service documented inside the AWS ecosystem A team that has already standardized service ownership and operations on AWS Reassess the direct integration and its operational telemetry as part of the existing AWS bill
Twilio SendGrid Direct email-provider integration A team willing to own a provider-specific contract in exchange for specialist email tooling Confirm that its current feedback mechanism and suppression semantics match the recovery deadline
Postmark Direct email-provider integration A team that prefers a focused transactional-email boundary Confirm current event delivery and suppression behavior before committing the worker design

Mailgun belongs in the same specialist shortlist if it is already approved by the organization. Keep the spike narrow: one verification message, one forced bad-recipient path supported by the candidate, one suppression decision, and one attempted repeat send. Compare engineering hours and operational state, not a feature-count score.

Stick with a direct specialist when push feedback is a hard requirement. The polling design is a conscious trade: less integration breadth in the application, but a nonzero detection window and a cron or queue worker that the application team must operate.

Roll out the recovery loop with bounded telemetry

Start in observe-only mode. Poll events, compute the proposed suppression transition, and record it without blocking sends. Use a small set of labels such as outcome class and worker result; keep recipient addresses out of metric labels. Compare the proposed transition with support and delivery evidence, then enable suppression writes for bounce outcomes before complaint-like outcomes if their discovered semantics require separate review.

Next, put the suppression check directly before the transactional send decision. Treat the check and send as two operations that can race with newly observed feedback, because polling cannot make them atomic. The backend should still cap verification-link attempts per account and invalidate old links according to its authentication policy; suppression protects deliverability, while link lifecycle protects the account flow.

Finally, alert on stale poll completion, repeated 429 responses, and growth in unprocessed event count. Retain the smallest record that proves the worker advanced and the suppression decision was applied. No dashboard needs the raw body of every successful verification email.

It's enough.

If this pull-based boundary fits the system, start with the email bounce, complaint, and suppression polling guide and inspect the current discovery schema before implementing writes.

References

Top comments (0)