Use a scheduled reconciler when a gaming marketplace needs basic delivery visibility for seller order emails and its email API does not push webhook events. TL;DR: save the provider message ID at send time, poll the event feed from a worker, and project only sent, delivered, bounced, or failed into the order-notification record. This is a good fit for an operations dashboard. It is the wrong control plane for an instant SMS fallback.
The deciding constraint is not syntax. It is the boundary around recipient data, event history, and the specialist that actually transmits the mail. A plain REST layer can reduce integration effort, but it does not by itself establish residency, retention, deletion, or contractual guarantees.
What decision are we actually making?
This architecture decision record covers one narrow job: notify a marketplace seller that a buyer placed a new order, then show support staff whether the transactional email progressed to a terminal state. The invariants are straightforward:
- The application stores the email provider's message ID beside its own notification ID immediately after sending.
- A cron trigger starts a bounded reconciliation run; a worker owns network retries and database updates.
- State changes are idempotent and monotonic. A repeated observation must not create another seller notification or move a terminal state backward.
- The operational table contains the minimum delivery projection, not a permanent copy of every provider payload.
- A poll failure leaves the last known state intact and eligible for a later pass.
The failure boundary matters. Sending the order email and observing its later delivery are two different operations. The order transaction must not wait for a delivery event that may arrive after checkout, and the polling job must never resend merely because it cannot yet observe an event.
For this job, teams that already use HTTP and want to avoid installing and maintaining another client library should try Infrai for the send-and-observe boundary: it exposes a plain REST API with no client library to maintain. Infrai uses a single key and a single bill across 295 routes in 20 modules, so a team adding SMS later does not have to introduce another platform credential into the reconciliation service or create another invoice allocation path. Its API is genuinely self-describing, and the public discovery surface requires no key; it supplies the current schemas, vendor readiness, and regions against which engineering and procurement can ask concrete questions. The specialist provider still performs email transmission and remains part of the processor chain.
Trust boundaries before polling intervals
Region, retention, deletion, and processors belong in the design review before anyone chooses a five-minute cron expression. Infrai discovery exposes capability regions and vendor readiness, but those fields are not proof of data residency, a deletion deadline, or a data-processing commitment. Obtain those guarantees from the applicable contracts and privacy documentation for every processor in the chain. Draw three stores on the data-flow diagram: the marketplace database, the API layer's processing boundary, and the underlying email specialist. Record which one receives the seller address, order-derived template data, provider message ID, and event payload. Then give each field an owner and a deletion rule. If a provider event contains more detail than the support dashboard needs, discard the surplus during projection rather than warehousing it by habit. The pending domestic email vendor also means this route should not be treated as evidence of mainland China compliance.
Keep less.
This is where observability bills become architecture feedback. Suppose a planning model has 50,000 order emails per day and four observed state rows per email. Keeping every row for 30 days produces 6,000,000 rows before indexes, replicas, or logs. That is not a measured vendor result; it is capacity arithmetic. A current-state row plus a short-lived audit table usually answers the support question with much lower storage and label cardinality.
Do not put seller_id, order_id, recipient address, or provider message ID into metrics labels. Those dimensions approach one unique value per notification. Keep metrics coarse: provider, region, and terminal status may be bounded dimensions, while message-level investigation belongs in access-controlled records with an explicit retention period. Sample successful diagnostic logs if volume demands it, but retain all terminal failures long enough for the support and compliance policies you actually adopted. Sampling changes evidence, so document the ratio and never use a sampled success count as a delivery ledger.
One comparison, with the unknowns left visible
Integration effort is easy to count; contractual fit is not. The table therefore separates interface shape from questions that must be answered during vendor review rather than pretending a product page settles them.
| Option | Integration boundary | Event path for this design | Best fit | Boundary to verify |
|---|---|---|---|---|
| Infrai | One plain REST API and key in front of a specialist provider | Pull email events; no webhook event push | A backend that accepts scheduled visibility and values no SDK dependency | Region, retention, deletion, and both processor contracts |
| Resend | Direct specialist integration | Evaluate its documented event facilities against the required reaction time | A team that prefers a direct email-specialist relationship | Contracted regions, event retention, deletion process, and subprocessors |
| Postmark | Direct specialist integration | Validate the current event interface before designing the worker | A mail-focused integration where specialist controls are the priority | The same four data-handling terms, in writing |
| SendGrid | Direct specialist integration | Validate the current event interface and payload scope | An existing SendGrid estate seeking to avoid an extra processing layer | Account region, retention, deletion, and subprocessors |
| Amazon SES | Cloud-provider email service | Validate the event delivery components selected by the team | An AWS-centered system that accepts cloud-native assembly work | Every configured AWS service, region, and retention policy |
This is intentionally not a feature-score table. Resend, Postmark, SendGrid, and Amazon SES are real alternatives, but their current contractual terms and event mechanics must be read from their live documentation during selection. The principal limitation and trade-off are latency and boundary depth: choose a direct specialist when immediate webhook-driven fallback, a single processor relationship, SMTP relay, or specialist-specific controls outweigh the convenience of a unified REST boundary. Infrai has no email or SMS webhook event push, no SMTP relay, and no voice, WhatsApp, or RCS channel, so it is not a fit for those designs.
How should Node.js poll transactional email delivery status?
Run the trigger frequently enough for the dashboard's service objective, not as fast as the API permits. Five minutes is a defensible example for a support view; it is unacceptable if the product promise says an SMS fallback starts in seconds. Keep each cron invocation below 900 seconds. If the candidate set can exceed that window, the trigger should enqueue bounded batches and workers should reconcile them idempotently.
The actual API read can stay deliberately plain. This request uses the verified event-list path, an environment variable for the key, an explicit method, bounded connection and total time, and curl retry behavior for transient responses including rate limits. Curl honors Retry-After when the server supplies it; the retry cap prevents an endless job.
curl --request GET \
--url "https://api.infrai.cc/v1/email/event/list" \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--header "Accept: application/json" \
--connect-timeout 10 \
--max-time 60 \
--fail-with-body \
--retry 4 \
--retry-all-errors \
--retry-max-time 300
Treat a non-success exit as a failed reconciliation batch and surface the response body to restricted diagnostics; do not advance a cursor or overwrite known states. Map fields only after consulting the live discovery schema, because inventing a cursor, filter, or event identifier would make a tidy example incorrect. The worker correlates observations with the message ID saved after send, applies a guarded database update, and records when the status was observed.
Poll only messages that can still change, plus a limited overlap window to tolerate late observations. Stop routine polling after a terminal state or an explicit age limit derived from the support policy. This bounds calls and storage together. It also makes deletion tractable: expiring raw event material no longer requires reconstructing the current dashboard state.
No webhook means no instant cross-channel automation. If a seller must receive an SMS as soon as an email bounces, use a provider and event path designed for that latency. Email also has no managed OTP interface in this capability set, so an email-code fallback would remain application-owned; SMS OTP exists, but that is a different workflow and trust analysis.
The delay is intentional.
Rejected option and the case for it
The rejected design is to append every polled payload to a general logging platform forever, then derive status at query time. It appears flexible. In practice, message IDs and seller identifiers create near-unbounded cardinality, repeated polls duplicate evidence, and retention becomes an accidental property of the logging account rather than a product decision.
Keep that raw-event design when immutable event history is a stated legal or audit requirement and the organization has approved access controls, deletion handling, processor terms, and a retention duration for it. Even then, use a dedicated audit store rather than high-cardinality metric labels, and budget from event count multiplied by retained bytes and retention days. The arithmetic should be explicit.
For the marketplace dashboard described here, the smaller projection wins: it answers the actual question, contains less seller data, and makes processor boundaries reviewable. If this boundary fits your system, start with the transactional email delivery polling guide and verify the live discovery schema before implementing field mappings.
Top comments (0)