spatie/laravel-rdap
Query domain registration data in Laravel with RDAP, the structured JSON successor to WHOIS. This package wraps basic RDAP lookups and adds response caching, configurable TLD server caching, and automatic retries with timeouts for unreliable endpoints.
Architecture fit. spatie/laravel-rdap is a thin, opinionated wrapper around the RDAP protocol (the structured-JSON successor to WHOIS). It exposes a facade (Rdap::domain(), Rdap::ip(), Rdap::dns(), Rdap::domainIsSupported()), returns typed response objects (DomainResponse, IpResponse) with convenience accessors (registrationDate(), expirationDate(), hasStatus(), get() with dot notation, all()), and ships a config file for retry/timeout and TLD-server cache behavior. Architecturally it belongs in the "integration adapter" layer of a Laravel monolith or a small domain-intelligence service — not in a hot request path and not as a system of record. It is a query client, not a data pipeline.
Integration feasibility. Very high on paper: composer require, one vendor:publish, then facade calls. It fits any Laravel 8+–12 codebase (PR #39 added Laravel 12 support; PR #40 fixed a PHP 8.4 deprecation), which matters because it signals the maintainer is keeping pace with the framework. No database migrations, no queue workers, no external services to provision beyond outbound HTTPS. A competent Laravel engineer can produce a working spike in under a day.
Technical risk. The risks are ecosystem and protocol, not code:
.be is called out as returning false from domainIsSupported). Any product requirement implying "look up any customer domain" is unsupported by this package alone and needs a WHOIS fallback path.domain()/ip() call is a blocking HTTP round trip with up to 3 retries × 5s timeout + 1s sleeps — a worst case of ~18s per lookup. There is no batch API, no queue integration, and no async primitive. Bulk enrichment must be built by us on top of it.tld_servers_cache. The typo timeoutInSecons in the documented parameter name suggests the README was not validated against the code. Both are yellow flags for a package we'd depend on.Key questions for the team.
RdapIpV4), or is this domain-only? Scope changes the surface area.Stack fit. Native fit for a standard Laravel stack (Composer, service container, config, facades, Carbon). It requires no infrastructure beyond outbound HTTPS egress to IANA and registry endpoints (data.iana.org, rdap.verisign.com, rdap.arin.net, etc.). If we run behind a locked-down egress proxy or in a VPC with restricted egress, that allowlist becomes a prerequisite ticket — flag it early, it is the most common surprise.
Migration path. There is nothing to migrate from unless we already run raw WHOIS or cURL calls to RDAP endpoints. In that case:
DomainLookupService) rather than calling the facade directly in controllers/jobs. This is the single most important decision — it decouples us from a low-dependency package and makes a future swap or fork a one-file change.Compatibility. Confirm our Laravel and PHP versions against the release line (Laravel 12 / PHP 8.4 fixes are the most recent movement). Pin the version explicitly in composer.json and commit the rdap.php config to version control rather than treating it as a local artifact — the retry defaults (3 × 5s) are product decisions, not library defaults. Note the config exposes a store_name for the TLD cache; if we run multiple app servers, we must set this to a shared store (Redis) or every node will independently fetch and cache the IANA list.
Sequencing.
domain(), ip(), domainIsSupported() against a representative set of our real customer domains (not google.com). Measure supported-TLD ratio and p50/p95 latency. This single experiment resolves the biggest open questions.RdapException volume.Maintenance. Low code-maintenance burden, moderate dependency-maintenance burden. The package surface we touch is small and stable (RDAP itself is a settled IETF protocol). The recurring work is: framework/PHP upgrade compatibility (historically handled promptly by the maintainer — Laravel 12 in 1.1.1, PHP 8.4 in 1.1.2), and our own cache/fallback logic. Budget a few hours per quarter for dependency review, plus a defined fallback plan if the project goes quiet. Because we're at 0 dependents, we should assume we're one of very few production users and that bugs we find will be ours to fix or upstream via PR.
Support. No vendor SLA. Support model is: Spatie's GitHub issues, community PRs, MIT license (fork-friendly — this is the meaningful mitigation). Internal ownership should sit with the backend team that owns the calling feature; do not let this become an orphaned integration that nobody can debug. Document the TLD-coverage limitation in the runbook before launch, because "domain lookup returned nothing" will otherwise be triaged as a bug when it is expected behavior for unsupported TLDs.
Scaling. The package itself does not scale — it makes one blocking HTTP call per query. Scaling levers are ours to build:
store_name is configured to a shared store.Failure modes. Enumerate these explicitly in the runbook:
RdapRequestTimedOut — upstream slow; surfaces after ~18s of retries with default config. In a request path this is user-visible latency. Mitigation: short timeout + fewer retries for interactive calls, longer for jobs.InvalidRdapResponse — malformed upstream payload. Not retried away; treat as a data-quality signal and log the raw body.null return from domain() — ambiguous by design: it can mean "domain does not exist" or "registry returned nothing." If the product must distinguish these, we need additional logic; this ambiguity is a real UX risk.domainIsSupported() returns false (e.g., .be). Must be a designed state, not an error.Ramp-up. Trivial for anyone who knows Laravel — the facade and response accessors are self-documenting and the README's usage examples are directly runnable. Realistic ramp: half a day to productive, one sprint to own the integration end-to-end including fallbacks and observability. The non-obvious learning is entirely at the protocol edges (TLD coverage, null ambiguity, retry-latency math), not in the package API — which is exactly why the spike in Week 0 should test our real domain portfolio rather than canonical examples. Overall: a low-cost, low-risk, low-ceiling component — adopt behind an internal interface, with eyes open that we are near the front of the adoption curve.
How can I help you explore Laravel packages today?