Skip to main content
Laravel, shipping fast.

Here's the uncomfortable truth about a shared package: it doesn't remove coordination, it moves coordination somewhere more disciplined.

api-server, api-license, and api-ai each pin the same constraint in their own composer.json:

// composer.json
"require": {
    "webplo/api-infrastructure": "^1.2.11"
}

Three services, one version number, and that's exactly the point: none of them can drift into their own copy of what EnsureTokenIsValidMiddleware does. But a fix to that middleware, a change to how domain verification behaves, say, now has to reach three services, not one, before it's actually live anywhere. Tagging a new package version doesn't do that by itself. Each consumer's own constraint has to be bumped, and each consumer has to be re-verified on the new version, because "the package changed" and "every service that depends on the package still behaves correctly" are two different facts, and only one of them is automatic.

The fleet's own answer to this is a ritual, not a hope: composer update to pull the new version, then composer bump to write the resolved constraint back into composer.json, then composer update again to lock it, then the same two gates from Chapter 13, composer check, composer test, run fresh against the new dependency before the bump is committed.

composer update
composer bump
composer update
composer check
composer test

Skip the last two steps and you've done the easy 90% of the work, pulling a new version, and left the 10% that actually matters undone: proof the new version doesn't break the consumer. Do this once per consumer, every time the shared package changes, and a one-line fix in EnsureTokenIsValidMiddleware costs three PRs and three test runs instead of one, not because the fleet is inefficient, but because that's the real, honest price of guaranteeing three services can never quietly disagree about how a bearer token gets validated. A team that isn't willing to pay that price shouldn't extract the shared package in the first place, because the alternative, three copies of the same logic slowly drifting apart, is a debt that compounds silently instead of a cost you pay up front and can see.

This is why the shared surface has to stay small. Every class you add to api-infrastructure is a class every consumer now has to re-verify on every bump, forever. A shared package earns its keep by being the five or six things that truly must be identical everywhere. It doesn't earn its keep by being convenient.