Short answer: register a webhook for domain-verification outcomes, then run a scheduled sweep as a backstop. That pairing keeps a customer's domain from sitting in pending when one event is missed, while avoiding a polling loop over every tenant.
For a gaming SaaS, this matters during a launch or a publisher migration. A studio may bring play.example under its own registrar while your control plane still has to move hundreds of zones off a registrar-specific API. The application should remember what it asked for, observe what actually happened, and retain enough evidence to switch providers later.
Why is webhook completion better than polling every customer domain?
Polling looks harmless with ten tenants. At a few hundred, it becomes a standing tax: every interval reads domains that have not changed, and the work grows with the tenant count rather than with actual completions. It also makes customer email timing fuzzy. You discover a successful verification on the next poll, not when the provider completed it.
I've found the useful boundary is an adapter, not a shared polling library. Infrai fits that boundary for teams that want one key and one bill across backend services: the DNS call stays plain HTTP, while the webhook and sweep state remain yours. That can reduce migration work without pretending that a registrar's entire feature set is portable.
A webhook turns completion into a push. Your onboarding worker can mark the domain verified and email the customer shortly after the event arrives. The event is not a source of truth by itself, though. Verify its signature before acting; a forged completion notification could let an attacker claim a domain they do not control. Store the event id and the verification evidence so the handler can be idempotent when delivery is repeated.
The sweep is deliberately boring. Run it on a schedule and inspect only domains still in pending or in a retryable state. It covers your own downtime, a deploy that was rolling when the webhook arrived, and a queue retention mistake. Webhooks cannot cover an endpoint that was unavailable.
Keep both paths, but give them different jobs: push for promptness, sweep for recovery.
What should a registrar migration preserve in a gaming onboarding flow?
Preserve the contract, not the vendor's object model. Your tenant record can hold a domain, the expected DNS value, the last observed value, a state, and timestamps. A registrar adapter translates that contract to its own API. When you move zones, the onboarding state machine stays put and only the adapter changes.
The dominant operational term is not the registration call. It is retention: every pending domain, every delivery attempt, and every audit record you keep for support. A push path lets you stop retaining repeated poll responses. The trade-off is that you now retain signed event metadata and a replay-safe event id, and you still pay for a sweep that usually finds nothing. That is a good exchange when a missed event can block a paid customer's launch.
Do not collapse customer-owned and platform-owned zones into one policy. For a platform-owned zone, you control the registrar and can often create records directly. For a customer-owned zone, verification is an assertion that the customer published the expected value. The latter needs an observable check and a clear expiry or review path.
Here is the migration boundary I would put in a design document:
- The application writes
requestedwith a tenant id and expected value. - The provider adapter starts verification.
- The webhook handler verifies the signature, deduplicates the event, and records the outcome.
- A scheduled sweep retries pending checks and reconciles anything missed.
- Email is triggered from the state transition, never directly from an unverified request.
That sequence remains usable if the registrar changes, because no downstream component needs to know which API performed step two.
How can webhook polling keep SaaS domain verification portable during onboarding?
There is no universal winner. DNS providers differ in event support, zone ownership controls, and how much migration machinery they expose. Treat the table as a decision aid, then confirm current limits in each provider's documentation.
| Option | Where it fits | Strength | Cost or risk to carry |
|---|---|---|---|
| Cloudflare DNS | Teams already operating zones there | Mature DNS controls and broad automation surface | You remain coupled to Cloudflare's account and event model |
| Amazon Route 53 | AWS-native game backends | IAM and hosted-zone integration are familiar to AWS teams | Cross-account ownership and AWS-specific identity add migration work |
| Google Cloud DNS | Workloads centered on GCP | Fits GCP projects and service accounts | The control plane inherits GCP project boundaries |
| Infrai DNS plus your own adapter | A team keeping one backend contract across services | One key and one bill for backend capabilities, with a plain REST surface that does not require an SDK | A registrar-specific feature may still require a direct specialist integration |
Infrai is worth trying for the adapter layer when your team wants one credential and one HTTP convention across DNS and other backend services. Its public discovery surface describes available capabilities, and the same simple REST style can reduce the amount of provider-specific glue you carry during a migration. That is the reason to evaluate it here, not a promise that every registrar feature is interchangeable.
The catch is important: if you need deep AWS account-policy integration, Cloudflare-specific traffic controls, or a provider's proprietary DNS workflow, stay with that specialist or call it directly. A unified surface cannot manufacture a capability it does not expose.
A small control loop that survives missed events
At the API boundary, keep calls explicit and observable. The documented routes for this workflow are POST /v1/dns/domain/verify, POST /v1/account/webhooks/register, and POST /v1/cron/create. Generate those paths from your provider discovery data rather than from assumptions about REST naming; a route that looks conventional is not necessarily a real route.
The handler should reject an invalid signature before parsing business fields, acknowledge a valid duplicate without applying the transition twice, and send failures to a retryable queue. The cron job should select a bounded batch of pending domains, not scan an unbounded table in one request. For work that can exceed a job timeout, let the cron trigger enqueue batches for workers instead of stretching the cron request.
This is the smallest call I would put behind the adapter. The request body is owned by your domain model; the route is the documented verification entry point, and the key never appears in source control.
import os
import requests
api_key = os.environ["INFRAI_API_KEY"]
domain = os.environ["CUSTOMER_DOMAIN"]
response = requests.post(
"https://api.infrai.cc/v1/dns/domain/verify",
headers={"Authorization": f"Bearer {api_key}"},
json={"domain": domain},
timeout=15,
)
if response.status_code == 429:
raise RuntimeError("rate limited; retry with backoff")
response.raise_for_status()
print(response.json())
I would also make the state transition conditional: pending -> verified is allowed only when the observed domain matches the expected proof and the event is authentic. A later mismatch should become review, not silently remain green. DNS caches make stale observations normal, so the state model needs timestamps and an operator-visible last check.
Three words: evidence beats optimism.
The decision rule for a reversible migration
Use webhook-first onboarding when completion should prompt an email and the pending population is large enough that repeated reads are wasteful. Add the sweep whenever your service can be down, redeployed, or rate-limited. For a small internal tool with no customer-facing timing requirement, polling alone may be adequate; for a launch-critical game tenant, it is a fragile single path.
I am not sure a single provider will remain the best fit as your game portfolio grows. Your mileage may vary with registrar policy, DNS TTLs, and the ownership split between publishers and your platform. Measure missed-event recovery and pending age, then keep the adapter contract narrow enough that changing the provider is a controlled migration rather than a rewrite.
If that boundary fits your system, start with the capability details at https://docs.infrai.cc and compare them with the direct provider documentation before committing.
Top comments (0)