Which outside services does your Laravel app call?

Your Laravel app can run in the EU and still send data to US companies. How to list every outside service it calls, from composer.lock to .env.example.

In this post
  1. Which outside services does my Laravel app call?
  2. Where to look
  3. Packages can mislead
  4. How to judge each service
  5. An example list
  6. The sovereignty scan does the reading for you
  7. What a list like this cannot tell you
  8. And once it is in order
  9. In short

You moved your Laravel app to a European cloud. The servers are in Paris, the provider is French, the contract is in your name. Then somebody asks where the data goes after that, and you realise you are not sure. The password reset mail, the card payment, the exception with a request body attached, the search index: each of those leaves your app and lands at a company somewhere.

This post shows how to make that list for a Laravel app, where to look, how to judge each service, and what a list like that can and cannot tell you.

Which outside services does my Laravel app call?

Usually more than you remember, and most of them are written down in three files: composer.lock, package.json and .env.example. The packages name the services your code talks to, and the environment variables name the drivers and hosts the framework sends data to. Read those three and you have most of the list.

Hosting in the EU answers where your app runs. The services it calls decide where its data goes next. A sovereign server that sends every exception to an American error tracker is only as sovereign as that error tracker.

Where to look

Each file gives away a different kind of service.

File What it shows Examples
composer.lock PHP packages, including the ones pulled in by others stripe/stripe-php, sentry/sentry-laravel, laravel/cashier
package.json Scripts that run in your visitors' browsers @sentry/vue, posthog-js, @stripe/stripe-js
.env.example Which driver Laravel uses, and which host MAIL_MAILER=postmark, QUEUE_CONNECTION=sqs, AWS_ENDPOINT

Prefer composer.lock over composer.json. The lock file lists every installed package, so a service that comes in through another package shows up as well. laravel/cashier, for example, means Stripe, even when stripe/stripe-php is nowhere in your own composer.json.

The frontend matters as much as the backend. A script in package.json runs in your visitor's browser and talks to its company directly, with the visitor's IP address, without your server in between.

Warning

Use .env.example, not .env. You only need the names of drivers and hosts, never a password or key, and a real .env does not belong in a browser tab or a chat window.

Packages can mislead

A package name is a hint, not proof. A few Laravel cases where the obvious reading is wrong:

  • The s3 disk is not always Amazon. league/flysystem-aws-s3-v3 speaks to any S3-compatible store. AWS_ENDPOINT tells you which: an address with scw.cloud is Scaleway Object Storage, r2.cloudflarestorage.com is Cloudflare R2, no endpoint at all is Amazon S3.
  • QUEUE_CONNECTION=sqs is not always Amazon either. Scaleway Queues speaks the SQS protocol. An SQS_PREFIX with scw.cloud in it means the jobs wait in France.
  • Reverb pulls in Pusher's packages. Laravel Reverb speaks Pusher's protocol, so pusher/pusher-php-server and pusher-js show up in an app that never talks to Pusher. With laravel/reverb installed and BROADCAST_CONNECTION=reverb, broadcasting runs on your own infrastructure.

Software that runs where your app runs, such as Reverb, has no company in between at all. It belongs on the list, but not as an outside service. (On Brewless, Reverb runs as Realtime, in a container of its own next to your app.)

How to judge each service

For every service on the list, write down two things: where the company is headquartered, and whether it has a parent company somewhere else.

The parent matters because ownership decides whose law applies. A company headquartered in the EU but owned by a group outside it can still be reached through that group. The other way round works too: a company outside the EU that belongs to a European group is not the same as an independent American one. Mailgun is a good example of a mixed case, a US company that is part of Sinch, from Sweden.

A simple rule keeps the list consistent: a service is European when the company and its parent company are both headquartered in the EU. Everything else is outside, however good its privacy page reads.

An EU region is not the same thing

Many US services offer to keep your data in an EU region. Sentry, PostHog, Algolia and Amazon itself all do. That is worth turning on, because it keeps data out of US data centres. It does not change who runs the service. The US CLOUD Act lets US authorities require a US company to hand over data it controls, wherever it is stored.

So note the region separately: "US company, EU region available" is a better answer than plain "US", and a worse one than "EU company".

An example list

Here is what the list could look like for a typical Laravel SaaS:

Service Found through Company European?
Stripe laravel/cashier United States No
Postmark MAIL_MAILER=postmark United States No
Sentry sentry/sentry-laravel, @sentry/vue United States, EU region available No
Algolia SCOUT_DRIVER=algolia United States, EU region available No
Scaleway Object Storage AWS_ENDPOINT with scw.cloud France Yes
Reverb laravel/reverb Runs where your app runs Not an outside service

Every row that says "No" is a decision. You replace the service, or you keep it on purpose and write down why. Both are fine; not knowing is not. The post on European alternatives for the services Laravel calls has options per category, from Mollie and Lettermint to Flare and Meilisearch.

The sovereignty scan does the reading for you

Going through three files by hand works, but it is slow and easy to get wrong in the cases above. So we built the sovereignty scan, a free tool on brewless.eu.

You paste or drop composer.lock (or composer.json), package.json and .env.example. The scan knows about seventy services, grouped into mail, payments, error tracking, analytics, search, real-time broadcasting, file storage, queues and cache, SMS and chat, AI models, sign-in, bot checks and maps. For each service it finds, it shows:

  • which package or line gave it away;
  • the company behind it and where it is headquartered, including a parent company;
  • whether that company offers an EU region;
  • European options for that category, where there are any.

It handles the misleading cases above: a Scaleway endpoint behind the s3 disk counts as Scaleway, not Amazon, and Pusher's packages do not count when Reverb is there. At the top it sums up how many of the outside services come from a company headquartered in the EU.

Note

The scan runs in your browser. Your files are never sent anywhere. If you want the result as a PDF, only the list of services found goes to Brewless, together with your email address. Our sales team hears that you asked, and the address is deleted after 30 days.

The facts in the scan were checked against each company's own pages on the date the result shows. Ownership changes, so check a provider yourself before you rely on it.

What a list like this cannot tell you

A list of services is a good start, not a full answer. It leaves out a few things:

  • Where the app itself runs. No file in your repository says which cloud your containers are on. That is the first question, and the guide to EU-sovereign Laravel hosting covers it.
  • Calls without a package. A service you call with Laravel's Http client and a hardcoded URL leaves no trace in these files. Search your code for Http:: and https:// to find those.
  • Fonts and scripts from a CDN. A <link> to a font service in a Blade layout sends every visitor's IP address there. Look through your layouts, or serve fonts through Vite yourself.
  • Your team's tools. Source hosting, CI, chat and the laptop of a developer abroad are a separate question from what the app calls.

And once it is in order

When your hosting and your services are European, you may want your visitors to know. Brewless gives every application a "Hosted & owned in Europe with Brewless" badge in the console, in light or dark, to paste into your footer. The HTML holds the image itself as inline SVG, so your visitors load nothing from Brewless when it shows: no script, no image request, no cookie. It links to the Built in Europe list, where your organisation can put the app forward; a person at Brewless reads each entry before it shows. Badge and the Built in Europe list has the details.

The badge says where the hosting is. Your list of services is what lets you stand behind it.

In short

  1. Read composer.lock, package.json and .env.example; together they name most outside services.
  2. Watch for the misleading cases: the s3 disk, SQS-compatible queues and Reverb.
  3. For each service, write down where the company and its parent are headquartered. Both in the EU means European.
  4. Treat an EU region at a US company as better than nothing, not as European.
  5. Replace each outside service, or keep it on purpose and write down why.

The sovereignty scan does steps 1 to 3 in your browser in a few seconds.

Frequently asked questions

How do I find out which outside services my Laravel app uses?

Read composer.lock for PHP packages, package.json for the frontend, and .env.example for drivers and hosts such as MAIL_MAILER or AWS_ENDPOINT. Together they name most services an app talks to. The Brewless sovereignty scan does this for you in the browser.

Is a service with an EU region European?

No. An EU region keeps the data in the EU, but the company that runs it is still headquartered where it is. If that is the United States, the US CLOUD Act lets US authorities require it to hand over data it controls, wherever that data is stored.

Does the sovereignty scan upload my files?

No. The scan runs in your browser and your files are never sent anywhere. Only when you ask for the PDF report does the list of services found go to Brewless, with your email address, which is deleted after 30 days.

Should I paste my .env file into the scan?

No, use .env.example. The scan only needs the names of drivers and hosts, never a password or a key.

What can the scan not see?

Where the app itself runs, services called with plain HTTP and no package or variable of their own, and the tools your team uses around the app, such as source hosting, CI and chat.

All posts Read this post as markdown

Try it on your own app

Brewless deploys your Laravel app to Scaleway and bunny.net, in your own accounts. Start free with one application, production included.