eightpoints/guzzle-bundle
EightPoints GuzzleBundle integrates Guzzle 6.x/7.x with Symfony, letting you configure HTTP clients in YAML, register services, and add plugins such as retry, logging, and caching. It supports Symfony 5–8 and PHP 7.2+, with a Flex recipe and event hooks.
Build vs. buy vs. framework-native (integration layer). The bundle is a configuration layer over Guzzle, not a new HTTP client. Adopting it is a decision not to build an in-house "API client registry" (base URLs, auth, timeouts, headers, retries, logging) — that glue is the recurring cost most platform teams quietly rebuild. The buy option is cheap (MIT, no license spend), and the "framework-native" alternative (Symfony's own symfony/http-client) is the genuine competing option you should decide against explicitly in an ADR.
Vendor-integration roadmap and time-to-market. Because every client is declared in config/packages/eight_points_guzzle.yaml (base_url, auth, headers, curl options, timeout, lazy loading), adding a new third-party provider (payments, CRM, tax, shipping, KYC) becomes config plus a thin service rather than an architecture project. This lets you commit roadmap dates for "support provider N" with far less engineering variance, and it makes per-environment differences (sandbox vs. production base URLs, credentials via env vars) a deployment concern instead of a code branch.
Reliability and service-level policy. slow_response_time (ms threshold) plus per-client timeout and the supported retry plugin let you turn "third-party APIs are flaky" into an explicit, reviewable policy: which integrations retry, how many times, what counts as slow, and where the error budget sits. This is the material you need to negotiate SLAs or justify circuit-breaker work.
Observability and supportability features. Logging into Symfony's default logger with a known format (eight_points_guzzle.{level}: {method} {uri} {code}), the debug toolbar/profiler panel, and the pre_transaction / post_transaction events (generic and per-client) give you a cheap way to deliver audit trails, PII scrubbing, correlation-ID propagation, and cache-control headers as cross-cutting listeners instead of copy-pasted code. Client-specific listeners overriding generic ones is a useful governance property: platform defaults, team overrides.
Security and compliance decisions. Centralizing auth, headers, and curl sslversion in one reviewed config file is a control, not just convenience — it makes "no hardcoded credentials," TLS version pinning, and header hygiene auditable in one place rather than across N service classes.
Platform lifecycle / upgrade decisions. Recent releases show active Symfony-version tracking (Symfony 5–8, including SF8 support in v8.6.0 and PHP 8.4 deprecation fixes), so this does not block a Symfony major upgrade. Low lock-in: configured services are plain Guzzle clients (eight_points_guzzle.client.<name>), so an exit is a DI alias change — which is exactly why the README's "create aliases" suggestion is worth enforcing as a team standard.
Use cases that fit: a Symfony monolith or modular monolith with 3–15 outbound HTTP integrations; multi-tenant SaaS with per-tenant credentials; internal platform teams standardizing how product squads call external APIs; environments where developers need request-level visibility without a paid APM.
Use cases that do not fit: Laravel applications (see below), single-integration products, or anything needing streaming, HTTP/2 multiplexing, or high concurrency.
Adopt when all of the following hold:
Illuminate\Support\Facades\Http client (which wraps Guzzle) — there is no product reason to install this there.symfony/http-client is simpler and the config indirection is pure overhead (YAGNI).symfony/http-client.Look elsewhere — or decide against adopting — when:
symfony/http-client is the Symfony-blessed HTTP abstraction, supports PSR-18, async/streaming, and needs no bundle glue. If your org policy favors fewer third-party bundles, that's a legitimate and probably stronger default; the counter-argument is Guzzle's plugin ecosystem and your team's existing familiarity.Recommended decision process: timebox a one-sprint spike that ports two existing integrations, one authenticated and one with retries, and measures (a) lines of glue code removed, (b) profiler/log usefulness in a real incident drill, (c) behaviour under timeout and 5xx. Then write the ADR choosing between this bundle, symfony/http-client, and raw Guzzle.
For executives (one paragraph). We spend recurring engineering time rebuilding the same plumbing every time we connect to a third-party API — credentials, timeouts, retries, logging, audit trails — and every rebuild is a place where security and reliability standards drift. This package is a free, MIT-licensed, actively maintained Symfony component that replaces that plumbing with reviewed configuration: integrations are declared in one file, requests and responses are observable and interceptable, and each vendor gets consistent timeout and retry behaviour. The business outcome is faster, cheaper onboarding of new providers, fewer production incidents caused by third-party flakiness, and a cleaner audit story for credentials and TLS settings. It is a low-cost, low-lock-in decision — clients remain standard Guzzle clients, so we can back out with a configuration change — but it is Symfony-only, so it does not apply to our Laravel services, and it carries a small-project maintenance risk that we mitigate by assigning an internal owner and keeping an exit path. Ask: approve a one-sprint evaluation spike, not a permanent commitment.
For engineering leads (summary).
eight_points_guzzle.client.<name>) in the DI container, with a Flex recipe, autowiring support, and a documented config reference.slow_response_time thresholds) for free; generic and per-client pre_transaction/post_transaction events as the sanctioned place for correlation IDs, audit logging, PII scrubbing, and header policy — no more bespoke middleware per integration.crm.client: '@eight_points_guzzle.client.crm') so a future swap to symfony/http-client is a one-line change per consumer.symfony/http-client. Success metrics: integration lead time per new provider, share of outbound calls with enforced timeout/retry, and count of third-party incidents traced via profiler/logs.How can I help you explore Laravel packages today?