huluti/geoip2-bundle
Symfony bundle for MaxMind GeoIP2 that resolves IP addresses to geographic data such as country, city, and coordinates using local databases, with service integration for looking up visitor locations in applications.
What the package actually is. Unchanged by 3.0.0. huluti/geoip2-bundle is a Symfony bundle, not a Laravel package. Its entire value proposition is dependency-injection glue: it registers the MaxMind geoip2/geoip2 client as a Symfony service, exposes a YAML config tree (database path, license key, locales), and lets you inject a configured reader into your services. The real work — parsing .mmdb files, IP-to-location lookups — is done by MaxMind's official library, which is a dependency, not part of this repo. 3.0.0 does not add features, does not touch the lookup path, and does not introduce a framework-agnostic entry point.
What 3.0.0 actually changes. This is a maintenance-only, hygiene-focused major: support for PHP 8.4/8.5, removal of old Symfony and PHP constraints, a bump of the underlying GeoIP2 dependency from v2 to v3, and tooling upgrades (PHPUnit, PHPStan). The versioned surface it moves is the Symfony/PHP axis — precisely the axis that does not apply to us. Two things are worth flagging for a TPM: (a) the release is described as the "initial fork release since the fork of gpslab/geoip2," so we are now looking at a fork of a fork, which lengthens the provenance chain and further weakens any assumption of upstream accountability; (b) the notes themselves contain an obvious typo ("Upgrade PHP Unot") and defer all substance to UPGRADE-3.0.md, which is a weak signal on release discipline for a package that would otherwise be asking us to trust its versioning.
Architecture fit. Poor, and unchanged. Laravel has no bundle/extension system; there is no Kernel::registerBundles(), no configuration tree compiler pass, and no autowired service container that this package's DependencyInjection/*Extension class can target. Attempting to install it into Laravel yields a package that does nothing at runtime. Dropping old Symfony versions in 3.0.0 makes the Symfony coupling narrower, not looser — it is still Symfony-only. A TPM should continue to treat this as "reference implementation for how to wire GeoIP2," not "installable dependency."
Integration feasibility. High, if we route around the bundle, and 3.0.0 does not change that calculus. The underlying geoip2/geoip2 package is framework-agnostic PSR-4 PHP and drops into Laravel cleanly: one service provider, one config file, one singleton binding. Estimated effort for a working Laravel integration remains 1–2 days including tests. The bundle's remaining reference value is the config key set (database paths per edition, license key, locale fallback chain) — and 3.0.0 did not change those keys, so any notes we took from the prior version remain valid. Note that 3.0.0 now expects geoip2/geoip2 v3; since we would be installing v3 directly anyway, the bundle's dependency bump is neutral for us and mildly useful as confirmation that v3 is the current line.
Technical risk. Low technical risk, high supply-chain risk — the ratio is unchanged by this release. The code surface is still small and thin, so an abandoned upstream remains forkable in an afternoon. But the 3.0.0 notes reinforce rather than alleviate the concerns: still a single maintainer, still no dependents to surface regressions, now with an added layer of fork genealogy, and a release note set thin enough that we cannot reconstruct intent without reading the diff. Arguably the one genuine improvement is PHP 8.4/8.5 support, which removes a future objection about the wrapper going stale on modern runtimes — but that is a signal about the wrapper's upkeep, not about its fitness for Laravel. The risk that actually matters is still MaxMind's data licensing and the weekly database refresh obligation, which no wrapper shields us from.
Key questions.
Stack fit. Laravel 10/11/12 on PHP 8.1+ with geoip2/geoip2 v3 (which pulls maxmind-db/reader). Ignore the bundle's Symfony version constraints entirely — 3.0.0 rewrote them, and they still describe compatibility with a framework we do not run. If anything, 3.0.0's dropping of older Symfony lines makes it less likely to install cleanly in a mixed tree, which is a further argument for not trying.
Migration path. Unchanged in shape. If the bundle is already in the tree from a prior Symfony service, the path is: extract the config values (config schema is stable across 2.x → 3.0, so extraction notes from a prior assessment still hold), drop the bundle requirement, add geoip2/geoip2 v3 directly, and reimplement the four or five lines of container wiring as a Laravel service provider. If that legacy Symfony service is staying alive on 2.x, treat the 3.0.0 upgrade as its own scoped ticket — it drops old Symfony and PHP versions and bumps the underlying library a major version, so it is not a patch-and-forget bump. If this is greenfield, skip the bundle from the start. Either way, define a GeoLocator interface in our domain layer and bind the MaxMind reader behind it.
Compatibility. The only compatibility axis that matters is maxmind-db/reader against our PHP version and the MMDB file format version (currently 2.0, unchanged by this release). Both are stable. Pin the reader version explicitly rather than inheriting whatever the bundle's lockfile implied. Aligning on geoip2/geoip2 v3 matches what 3.0.0 expects, so there is no divergence to manage if we ever need to compare behaviour against the bundle.
Sequencing.
UPGRADE-3.0.md and re-verify config keys survived the major bump.Maintenance. Recurring, non-optional work, unaffected by 3.0.0: the MMDB file must be refreshed weekly (MaxMind ships twice weekly) via a licensed geoipupdate job or a signed download in your pipeline. GeoLite2 requires a MaxMind account and license key; the data is CC BY-SA 4.0 and requires attribution in user-facing materials. Budget an hour a month of ownership plus an alert when the file age exceeds ~14 days. That maintenance burden is identical whether or not we use this bundle.
Support. No vendor support channel, no maintainer SLA, no downstream community to consult, and 3.0.0 does not change that — a fork release with a one-line changelog and a typo is not evidence of a support motion. Supportability continues to come entirely from the official MaxMind library, which is well-documented. Internal support cost remains dominated by "why did geo-resolution return null," solved by structured logging at the resolver boundary, not by package choice.
Scaling. No change. Local MMDB lookups are memory-mapped, in-process, and roughly microsecond-scale — no network hop, no external service to capacity-plan. Two real constraints persist: file size (GeoLite2-City is on the order of tens of MB) duplicated per container/pod, and cold-start page faults when the map is first touched. For request-path use, add an in-process LRU keyed by IP; hit rates are typically high because client IPs repeat within a session. If lookup volume grows into the millions per hour, move enrichment off the request path entirely.
Failure modes. Design for these explicitly: (a) database file absent or unreadable at boot — the default implementation must degrade to "unknown," not throw a 500; (b) stale file — silently wrong answers, which is worse than no answer, so alert on file mtime; (c) AddressNotFound for private, loopback, and IPv6-mapped addresses — normalize and short-circuit before the lookup; (d) license lapse — downloads start failing, and the failure only surfaces at the next refresh, so alert on the updater, not the app; (e) corrupt/truncated file from an interrupted download — write to a temp path and atomically rename. Add one supply-chain failure mode surfaced by this release: a major version bump to a low-traffic fork with thin release notes is hard to audit after the fact, so if any part of our estate does depend on the bundle, pin it and diff before upgrading.
Ramp-up. Unchanged. A Laravel engineer unfamiliar with GeoIP2 needs roughly half a day to be productive: the API is small ($reader->city($ip)), the data model is documented, and the failure semantics are learnable from the exceptions. The bundle contributes nothing to that ramp-up and arguably adds confusion by implying a framework dependency that doesn't exist in our stack. PHP 8.4/8.5 support in 3.0.0 is the only item a new engineer would notice, and it is not a reason to read this package.
Recommendation. Unchanged by 3.0.0: adopt the pattern, reject the package. Use MaxMind's official geoip2/geoip2 v3 behind an internal interface, own the refresh job, and revisit the build-vs-buy question against edge/CDN geo headers before committing to the database-refresh obligation at all. Treat 3.0.0 as confirmation of the original read — a wrapper maintained on the Symfony/PHP axis, with no Laravel-facing capability added — and keep it in the "design reference only" column.
How can I help you explore Laravel packages today?