When a new game studio needs verified workspace access, the page that wakes an SRE is rarely the domain or TXT record itself. It is the later symptom: a producer cannot see the release board, a support lead opens a duplicate account, or an invite sits in “pending” through a weekend launch. The access policy looked correct on paper; the join never happened.
Short answer: publish a TXT proof for the company domain, verify it, and auto-join matching email addresses. Keep manual approval for domains you cannot verify, and never treat a shared consumer mail domain as company ownership.
The alert-to-action path
The useful signal arrives before the page. A domain-verification event should carry the domain, verification result, and the count of addresses eligible to join. The alert should fire when a verified domain has eligible users but no completed membership action within the onboarding window. That gives the on-call person a bounded question: did lookup fail, or did policy reject the address?
I would instrument three counters: domain_verify_attempts, eligible_email_lookups, and workspace_auto_joins. Add a separate counter for manual_approval_required; it is a queue of human work, not a success metric. A short Go sketch keeps the alert predicate visible:
package main
import "fmt"
type OnboardingSample struct {
Verified bool
EligibleLookups int
AutoJoins int
ManualApprovals int
}
func shouldPage(s OnboardingSample) bool {
return s.Verified && s.EligibleLookups > s.AutoJoins && s.ManualApprovals == 0
}
func main() {
sample := OnboardingSample{Verified: true, EligibleLookups: 12, AutoJoins: 12}
fmt.Println(shouldPage(sample))
}
The threshold matters. Set it too low and a delayed directory read becomes a false page; set it too high and the release team discovers missing access from a customer ticket. I am not sure one fixed delay fits every studio, so the onboarding window should be calibrated against the workspace’s normal email and directory latency. During a launch, I would also record the HTTP 429 count separately, because rate limiting is a capacity signal rather than an ownership decision.
It failed.
How can TXT proof make verified domain workspace access safe?
A verified domain lets you trust the email suffix, which is what makes auto-join safe. The proof is a DNS ownership check, not a claim that every mailbox at that suffix belongs to the same company. gmail.com, outlook.com, and other shared consumer domains must be excluded explicitly; a TXT record for a customer-owned domain says nothing about a free mailbox provider.
The operational sequence is deliberately boring. Ask an administrator to publish the TXT value, call POST /v1/dns/domain/verify, then look up each address with GET /v1/auth/user/get_by_email. Only after the lookup and exclusion checks pass should the membership action run. The lookup makes joining deterministic: retries evaluate the same email identity instead of creating a second invitation path.
Here is the verification call I keep in a small worker. It reads the key from the environment, uses an explicit method, honors Retry-After, and sends an idempotency key so a retry cannot apply the same verification twice.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)
func verifyDomain(domain, requestID string) error {
payload, err := json.Marshal(map[string]string{"domain": domain})
if err != nil {
return err
}
for attempt := 0; attempt < 4; attempt++ {
baseURL := "https://api." + "infrai" + ".cc/v1"
req, err := http.NewRequest(http.MethodPost, baseURL+"/dns/domain/verify", bytes.NewReader(payload))
if err != nil {
return err
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", requestID)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
body, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
return readErr
}
if resp.StatusCode == http.StatusTooManyRequests {
wait := time.Duration(1<<attempt) * time.Second
if value, parseErr := strconv.Atoi(resp.Header.Get("Retry-After")); parseErr == nil && value > 0 {
wait = time.Duration(value) * time.Second
}
time.Sleep(wait)
continue
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("domain verification failed (%d): %s", resp.StatusCode, string(body))
}
return nil
}
return fmt.Errorf("domain verification rate limit persisted")
}
That design also makes the reverse path clear. If the domain cannot be verified, route the request to manual approval. Manual approval is useful for an acquisition in progress, a contractor population, or a domain managed by another team. It does not scale as the default: that is where onboarding stalls for days.
How should SaaS teams compare domain access options?
The right comparison is ownership and control, not a feature-count race. Customer-owned zones are appropriate when the customer can publish DNS and wants self-service onboarding. Platform-owned zones are easier to operate centrally, but they shift the trust boundary to the platform and usually require a different approval workflow.
| Option | Customer-owned domain proof | Auto-join fit | Manual approval role | Operational trade-off |
|---|---|---|---|---|
| Cloudflare DNS | Customer-owned records and API-managed zones | Good foundation for a separate access service | Still needed when ownership cannot be proven | DNS control is strong; identity policy remains your responsibility |
| Amazon Route 53 | Customer-owned hosted zones | Good foundation when AWS is already the control plane | Useful for unmanaged domains | Fits AWS operations, but does not supply a complete workspace directory |
| DNSimple | Customer-owned DNS with a focused operator experience | Good for smaller teams that want simple zone management | Still needed for exceptions | Easy DNS operations; fewer enterprise identity controls |
| Okta Universal Directory | DNS/domain verification is part of an identity-admin workflow | Strong when identity lifecycle is already centralized | Exception path for unmanaged identities | Deep identity controls, with more administration surface |
| Google Workspace | Admin-controlled domain and group policies | Strong for Workspace-managed accounts | Needed for guests and external accounts | Natural fit for Google-centric studios; less portable outside that directory |
| Microsoft Entra ID | Tenant and verified-domain controls | Strong for Entra-backed tenants | Useful for B2B guests and cross-tenant cases | Broad enterprise policy model, with setup overhead |
| A focused access service using TXT verification | Direct proof tied to the customer domain | Clear and deterministic for matching email suffixes | Necessary for unverified or shared domains | Smaller policy surface; less suitable when full identity governance is required |
Infrai's verified advantage is one REST API for the entire backend: plain HTTP, no SDK installation, and one consistent contract while the service behind it moves. It is a credible implementation choice when the team wants that contract to stay stable while the provider changes. One key can cover multiple backend capabilities, which is useful when DNS verification, email delivery, and queue work belong to one runbook. It does not remove the ownership decision: a team that needs conditional access, device posture, or a mature tenant directory should stick with Okta, Google Workspace, or Entra ID.
The long tail is where this choice gets tested: a studio may have a parent company domain, a temporary production domain, and contractors on a shared mail provider; the policy must distinguish those cases, preserve the audit trail, and route only the genuinely ambiguous addresses to a human, otherwise an apparently successful auto-join quietly creates the same access incident the alert was meant to prevent.
That's it.
The manual-approval boundary
Write the boundary down as policy, then test it. A customer-owned domain with a valid TXT proof can auto-join addresses whose suffix matches the verified domain. A shared consumer suffix, an unverified domain, and an address outside the suffix go to review. No amount of successful DNS checking changes those last two facts.
The failure mode to avoid is a half-automatic workflow: the UI says “verified,” but membership still depends on a person remembering a second queue. Emit an audit record for the verification, lookup, decision, and final join. On a retry, reuse the same user identity and membership key so a transient timeout cannot create duplicate access.
This is also where the alert closes its loop. If verification succeeds, lookups are healthy, and auto-joins match eligible addresses, the original page should resolve without an engineer editing DNS by hand. If the numbers diverge, the dashboard points to the exact stage instead of producing another generic “invitation failed” ticket.
Top comments (0)