koco/avro-regy
koco/avro-regy is a Laravel package for Avro schema management and schema registry integration. It provides configurable tooling to define, register, and resolve Avro schemas, helping PHP applications validate and serialize data with a registry-backed workflow.
Start by confirming the Symfony/Laravel gap. koco/avro-regy is a Symfony Messenger bundle, so Laravel package auto-discovery won't find it and there's no service provider or facade. v1.2.0 doesn't change that — it's a feature bump, not a Laravel bridge. You still have three realistic options: run it inside a sidecar Symfony Messenger worker alongside your Laravel app, treat it as a reference implementation and port the serialization logic into a custom Laravel queue serializer, or import the relevant classes directly and wire them yourself. Decide which before writing any code — this is the single biggest fork in the road.
Minimal install path:
composer require koco/avro-regy:^1.2 and then read the resulting vendor/koco/avro-regy/composer.json to see exactly which Symfony and Avro PHP constraints were resolved. The base release is still an October 2022-era codebase, so expect Symfony 5.4/6.x era dependencies even on the newer tag.requestOptions config — no forked client needed. Confirm the option shape in DependencyInjection/ rather than guessing at the README.config/bundles.php. In Laravel, skip the bundle registration and instantiate the underlying classes from a custom service provider or a queue serializer.Read, in this order:
README.md — the config tree (registry URL, subject naming strategy, serializer registration, and now requestOptions).DependencyInjection/ — the extension class enumerates every config key and its default. In a small bundle this is the documentation; the README will be thinner than you expect. This is where you confirm exactly how requestOptions is forwarded.SerializerInterface — this is the code you'll actually reuse, subclass, or copy.composer.json — tells you which Avro library and Symfony minor you're pinned to.First use case: register one flat scalar record schema (e.g. OrderPlaced) under orders-value, publish one message through the serializer, then consume it and confirm the decoded array round-trips. Don't start with nested records, unions, or logical types — start with something flat so you can hexdump the wire bytes and verify the magic byte + schema ID prefix. Once that round-trips against a plain local registry, re-run it against an authenticated registry with requestOptions set, so you validate the new feature before it's a blocker in staging.
Laravel-side integration. The most practical adoption is a custom queue serializer or a queue middleware that transforms specific jobs. Two patterns work well:
schema_id plus the binary payload in the queue row's data column. Decode on the worker before dispatch().AvroEncoded get Avro treatment; everything else passes through as normal JSON. This lets you adopt Avro incrementally instead of forcing the whole application onto it.Registry client configuration (requestOptions). This is the headline of v1.2.0 and it's the one piece of the bundle you'll likely touch in the Laravel path even if you don't use the bundle itself. Use it to:
Authorization/API-key headers in one place rather than hand-rolling a Guzzle client. This removes the previous "fork the client to add credentials" step for Confluent Cloud and locked-down on-prem registries.Because it's a passthrough to the underlying HTTP client, treat it as config you must test, not config you can reason about: a wrong option key is often silently ignored rather than rejected. Write one test that hits an authenticated registry and asserts a 401 becomes a clear exception.
Schema management.
.avsc files under resources/avro/ or a dedicated schemas/ directory, and publish them to the registry during deploy via a small artisan command (walk the directory, POST each file to /subjects/{subject}/versions).App\Events\OrderPlaced → orders-value. Inconsistency here is the root cause of most "it worked in staging" incidents.Consumer-side.
schema_id → schema locally (file cache or Redis). The bundle is thin; caching is your responsibility. Hitting the registry on every message is a latency and availability problem — and now that you can tune timeouts, the natural next step is to avoid the call entirely on the hot path.Symfony transport scoping. If you do end up inside Symfony Messenger, register the bundle's serializer per transport rather than as the default. Setting it globally will attempt to Avro-encode every message, including ones your other services expect as JSON.
Testing.
requestOptions, so credential and header regressions surface in CI, not during a deploy.CI/CD.
BACKWARD). Call the compatibility endpoint or use a schema CLI before deploying.config/avro-regy.php published for you. Budget real time for the glue layer. v1.2.0 is additive and does nothing to close this gap.requestOptions for the schema-registry client) with no stated breaking changes, but you're jumping 1.0.1 → 1.2.0 with no published notes for 1.1.0. Diff DependencyInjection/ and the client construction between tags before assuming a drop-in upgrade — the config tree is the thing that shifts in small bundles.requestOptions is opaque passthrough. Unknown keys may be ignored rather than rejected, so a typo looks like "auth works everywhere except production." Assert on real registry responses in tests, and log the effective config (with secrets redacted) at boot.composer audit over the transitive Avro and Symfony dependencies.composer.json before assuming a modern flix-tech/avro-php will drop in.requestOptions lets you set sane timeouts and retries, which is mitigation, not a fix: serialize lazily in the worker, or cache aggressively, and have a documented fallback path.orders-value, consumer reads order-events-value, and everything "works" until it quietly doesn't. Log both the subject and the schema_id on producer and consumer side.BACKWARD. Test registration in CI, not in production.null are where Avro PHP libraries diverge. Write an explicit test for every optional field; behavior differences here are subtle.SerializerInterface yourself is usually faster than fighting the bundle's opinions. For per-topic behavior you'll almost certainly need your own wrapper.requestOptions now available as a reference, wiring an authenticated registry client yourself is a shorter task than it was a release ago. For most Laravel shops that still beats maintaining a bridge to a low-adoption Symfony bundle. Adopt the pattern here, not necessarily the package.How can I help you explore Laravel packages today?