sensiolabs/consul-php-sdk
A thin PHP wrapper around the Consul HTTP API, covering agent, catalog, health, kv, session and txn services. Methods return a ConsulResponse and throw exceptions on 4xx/5xx errors, with handy lock and semaphore helpers for distributed coordination.
Architecture fit. This is a thin, framework-agnostic HTTP wrapper, not a Laravel package. Each Consul API surface (Agent, Catalog, Health, KV, Session, Txn, plus ACL, Config, Connect, Operator, Peering, PreparedQuery, Snapshot, Status as of v5.4.0) maps to a PHP service class with a uniform $service->method($required, $options) signature, a ConsulResponse value object, and typed ClientException (4xx) / ServerException (5xx). That is a good fit for a TPM's purposes: the abstraction boundary is honest, so we can wrap it in our own Laravel service provider and facade without the SDK fighting us. It is a poor fit as an application-facing API — there is no caching, retry, circuit breaking, or degradation logic, so every one of those concerns becomes ours.
Identity and provenance risk. The brief says sensiolabs/consul-php-sdk, but the package was renamed to friendsofphp/consul-php-sdk in v5.0.0 (namespace moved from SensioLabs\Consul to Consul). Two consequences: (1) our dependency manifest and SBOM must reference the new name or we will pin an abandoned artifact; (2) an unreserved legacy name is a dependency-confusion surface — confirm with whoever owns our private registry that sensiolabs/* is blocked or explicitly allow-listed. Dependents: 0 and 317 stars are a weak adoption signal, and the listed release date (2026-09-29) is inconsistent with the changelog history — treat the package metadata feed as unreliable and verify against GitHub directly before it enters a build.
Integration feasibility. Moderate, with one real friction point: the SDK requires symfony/http-client (≥6.4 on v5.4), while Laravel ships Guzzle. We would run two HTTP client stacks, two connection pools, and two sets of timeout/telemetry conventions. Acceptable, but it should be a conscious decision, not an accident. Otherwise requirements are cleanly satisfiable: PHP ≥8.2, psr/log 2.x/3.x, no framework coupling, no global state.
Technical risk.
CONSUL_HTTP_TOKEN from the environment works at bootstrap, but env() outside config/ returns null once php artisan config:cache runs. Token injection must go through a config file backed by a secret manager.Agent::join()/forceLeave() used the wrong HTTP verb until 5.4.0 (silent bootstrap failure), and MultiSemaphore reused metadata across resources (fixed in 5.4.0). Anyone on 5.3 inherits both.Key questions for the team.
LockHandler/MultiLockHandler, or keep Redis/DB locks for anything financially material?Stack fit. Target Laravel 10–12 on PHP 8.2+, with the SDK pinned to v5.4.x. Bind Consul\ClientInterface (introduced v5.1.0) in a container provider rather than instantiating services ad hoc — that single decision buys us test doubles, per-environment configuration, and a future swap point. Expose a narrow internal facade (Discovery::healthy('billing'), Config::get('feature.x')) so application code never imports the vendor namespace; that keeps the vendor surface to one directory and makes an exit cheap.
Migration path.
Agent/Catalog/Health read paths, confirm the token flows correctly under config:cache, and prototype one blocking query on a queue worker.laravel-consul composer package: config file, service provider, facade, cached catalog lookups, retry/circuit-breaker policy, structured logging, health-check route.Health-filtered Catalog lookups, behind a feature flag with a static-config fallback.Agent; deregistration on shutdown. This is the piece most likely to be underestimated.KV reads with blocking queries in a long-running worker pushing into the cache; Config service for environment-scoped values.Connect/mTLS, PreparedQuery/DiscoveryChain, Peering, Snapshot/Operator/ACL automation — valuable, but Phase 3+ and gated on whether we commit to Consul at all.Compatibility. Run composer why-not friendsofphp/consul-php-sdk 5.4.* early. The realistic conflicts are other packages pinning symfony/http-client below 6.4 or psr/log 1.x, plus any Laravel version constrained to older Symfony components. Both are resolvable but each is a multi-day conversation with the owning team. Also confirm the SDK's HTTP client does not silently inherit global Guzzle/Symfony defaults from a shared container.
Sequencing. Do not start with Connect. The dependency-name question, the Laravel shim, and the Consul-down degradation policy are the three items that block everything else and none of them are code-heavy. Resolve them before the first production call.
Maintenance. MIT, active, modernised codebase (readonly classes, PHPUnit 11+, phpstan, php-cs-fixer), and a credible umbrella org — these are genuine maintainability signals to cite in an architecture review. But it is a small-maintainer project with zero dependents on record; bus factor is the real risk. Mitigation: vendor the dependency into our monorepo (Composer path or Satis mirror) so a stalled upstream is a fork, not an incident. Budget roughly 0.1 FTE for the shim and upgrades, plus a quarterly review of upstream releases.
Support. Community-only: GitHub issues, no SLA, no vendor to escalate to. Our support model must be "platform team owns it, upstream is best-effort." That is fine for internal infrastructure glue and disqualifying if this is embedded in a customer-facing SLA without a fork. Establish an internal owner and a documented upgrade cadence before adoption.
Scaling. Every service class ultimately talks HTTP to a Consul agent; connection count, agent locality (sidecar vs. remote), and blocking-query worker count are the three dials. The SDK provides none of them. Specific concerns: no built-in connection reuse policy, blocking queries consuming FPM workers under Octane (where a blocked worker stalls a long-lived process), catalog read amplification if we query per-request instead of caching, and cross-datacenter latency now that dc is accepted everywhere — use local agents and cache aggressively.
Failure modes to design for now.
ServerException on every call; without a cache-first policy the application fails on a dependency that should be advisory.ClientException (403) surfaces as an application error; needs explicit handling and a rotation runbook using the CONSUL_HTTP_TOKEN/secret-manager path.config:cache; catch in the spike.Ramp-up. The API is easy to learn — a mid-level PHP developer is productive in a day on KV/Catalog/Health. The domain is not. Sessions, ACL policies, consistency modes, blocking-query indices, and datacenter semantics leak straight through the "thin wrapper" abstraction, so expect 1–2 weeks to competence on the read path and materially longer for locks and ACL automation. The larger cost is not developer ramp-up but operations ramp-up: someone must be able to run, back up (Snapshot), and reason about a Consul cluster. If we have no owner for that, the SDK is not the decision — Consul is, and it should be re-evaluated on its own merits.
How can I help you explore Laravel packages today?