cloudflare-r2data-residencyjurisdictioncomplianceobject-storage

Cloudflare R2 Jurisdiction: When Data Residency Isn't Enough

October 2026 · 21 min read · Surya

Cloudflare R2 Jurisdiction: When Data Residency Isn't Enough
  • R2 Jurisdiction pins bytes to a legal border, not to the rest of your stack
  • The EU R2 question has a specific answer, and it is not "EU-only"
  • A jurisdiction flag is a checkbox. Your audit trail is not.
  • Checklist: what jurisdiction does not cover in your R2 setup
  • Mounting R2 into a container is the request we get and cannot fill
  • Credentials from another account are a policy problem pretending to be a config problem
  • Who should not use Storafleet for this, and what to use instead

Does setting a jurisdiction on a Cloudflare R2 bucket actually keep my data in the EU?

Yes, for the narrow legal question of where the bytes rest. When you create an R2 bucket with a jurisdiction, Cloudflare constrains where that bucket's data is stored and processed. That is a real control, not marketing. It is the answer a lawyer asks for when the question is "which country's soil is this sitting on."

No, for almost everything else you probably meant by data residency. It does not stop your laptop from syncing a copy to Dropbox. It does not stop your CDN from caching objects at the edge in Singapore. It does not stop the operator with the admin token from reading a file from a café in Lisbon. It does not stop your backup job from replicating the bucket to a provider in Virginia. A jurisdiction flag is a pin on a map. Your stack is not a map.

Here is what this post covers: what the jurisdiction field on an R2 bucket actually constrains, why "Cloudflare R2 EU" is not the same as EU-only, why a jurisdiction flag is the start of a compliance argument rather than the end of one, a checklist of the gaps it does not touch, the FUSE-mount request we get constantly and cannot fill, why cross-account credentials are a policy problem wearing a config costume, and the readers who should close this tab and go run rclone. Some of them should. We will say which.

R2 Jurisdiction pins bytes to a legal border, not to the rest of your stack

A jurisdiction is a bucket-level setting in R2 that constrains where that bucket's data is stored and processed. That is the whole definition. You set it when you create the bucket, and from that point Cloudflare keeps the objects inside a defined set of locations. The mechanism is a config field. It is not a contract, and it is not a promise about your architecture.

Jurisdiction vs. residency

Data residency, by contrast, is a claim. It is usually a claim a vendor makes about themselves in a footer or a trust page. "Data residency" as a phrase means: for the purposes of a specific regulation or a specific customer contract, the data can be said to live in a named jurisdiction, and here is the evidence we can produce to defend that statement in front of an auditor. Residency is an argument backed by artefacts. Jurisdiction is a dropdown.

Conflating them is where most teams get into trouble. They see the jurisdiction field, pick the region, tick the box in the security questionnaire, and move on. Then a customer's procurement team sends back a 40-page vendor review asking about subprocessors, log locations, backup regions, and who at the company can read production data. The jurisdiction field answers none of those.

Think of jurisdiction as a constraint on the storage layer only. It says: the bytes in this bucket rest inside this border. It does not say anything about the compute that touches those bytes, the logs those operations produce, the metadata, the access tokens, the analytics pipeline, the cache, or the machine your engineer is reading them from. Every one of those is a separate question, and R2's jurisdiction setting does not answer a single one.

That is not a knock on R2. It is what the feature is. Cloudflare built a tool that solves a specific, narrow, real problem: keep the object bytes in a defined legal location. That is a valuable thing to be able to do. It is just not the same as the residency story people assume they are buying.

If you want the broader picture of what residency actually requires across multiple providers, that is a separate argument. This post is the R2-specific version of it. And if you're trying to work out where the rest of your stack sits relative to that border, our page on data residency is the place to start, because the bucket is one line item in that picture and not the whole of it.

The EU R2 question has a specific answer, and it is not "EU-only"

People search "cloudflare r2 eu" and land on marketing pages that do not quite say what they need. Here is the actual shape of the thing.

Jurisdiction is set at bucket creation. You pick it once, at the moment the bucket exists. If you have already created a bucket with the default (no jurisdiction) setting and your data needs to be in the EU, your options are: create a new bucket with the EU jurisdiction and migrate the objects, or accept that your existing bucket does not carry the setting. There is no "flip the switch" moment. Plan for this before you write your first object, because the migration is real work.

The config surface is the bucket creation call, whether you do it in the dashboard, with wrangler r2 bucket create --jurisdiction eu, or via the R2 API. The field is jurisdiction, and the value is a short region identifier, not free text. You cannot say "Frankfurt only" or "Ireland only." You pick from the set Cloudflare offers.

What "EU jurisdiction" actually buys you is a defined set of locations, not the whole of Europe. This matters because people read "EU jurisdiction" and assume it means their data will live in a specific country, or at least in a specific cloud region they already have a DPA with. It does not. It means Cloudflare keeps the data within the EU set of locations they operate. Good enough for GDPR-flavoured arguments. Not the same as "the bucket is in Frankfurt and only Frankfurt."

There are a few other things worth knowing about the field before you build on it.

  • It applies to the bucket, not the account. Different buckets in the same R2 account can have different jurisdictions, or none at all. If you have ten buckets and only one is EU-pinned, you have nine buckets that are not.
  • It does not constrain Cloudflare's operations of the service. It constrains where the data rests and is processed within the R2 product. It does not turn R2 into an air-gapped system with no global infrastructure involved in serving a request.
  • It does not follow the data out. If you copy an object from an EU-jurisdiction bucket to a bucket in another jurisdiction, or to another provider, the copy is where you put it. The jurisdiction flag is a property of the source bucket, not a tag that travels with the bytes.
  • It does not change your billing or your latency profile in a way you should plan around. Do not expect a jurisdiction setting to make your Frankfurt requests faster. That is not what it is for.

The honest summary: R2 jurisdiction is a real EU control for the layer it covers. If your only question is "can I defend the statement that these bytes sit inside the EU," the answer is yes, and the field is the mechanism. If your question is anything broader, the field is not the answer and no amount of reading the docs will make it one. Check the current Cloudflare docs for the exact jurisdiction values and the exact flag syntax before you script anything, because that surface has moved before and it will move again.

A jurisdiction flag is a checkbox. Your audit trail is not.

Residency is not a feature you enable. It is an evidence trail you maintain. That distinction is the entire reason a jurisdiction flag will not save you in a vendor review.

What a vendor review actually asks

Think about what actually happens when someone asks you to prove residency. It is almost never a single question with a single answer. It is a set of questions, and each one needs a document, a log, a config export, or a signed statement. The jurisdiction field is one line item. The rest is the work.

We have sat through enough of these (as the vendor being reviewed, and as the reviewer) to know the shape. Here is what an ISO 27001 auditor or a customer's security team actually asks when residency is on the table:

  • Where do the primary objects rest? (Jurisdiction answers this.)
  • Where do backups and replicas rest? (Jurisdiction does not.)
  • Where do logs go, and who can read them? (Jurisdiction does not.)
  • What subprocessors touch the data, and under what contracts? (Jurisdiction does not.)
  • Who at the company can access production data, and how is that access logged? (Jurisdiction does not.)
  • How do you prove any of the above is currently true, not just true on the day you created the bucket? (Jurisdiction does not.)

The last one is the killer. A config field is a snapshot. Compliance is a continuous claim. You set the jurisdiction on day one. On day 400, can you prove nothing changed? The setting did not change, sure. But the answer to "did anything change" is not the setting. It is the access log, the deploy history, the credential rotation record, the list of who had the admin token last quarter, and the process notes that show you check all of this on a schedule.

We are not going to pretend Storafleet solves this by magic. We do not have an auditor in a box. What we can do is hold the config surface in one place so that the evidence trail has a single origin, and so that when someone asks "show me the buckets we have, which ones are EU-pinned, and who has keys to them," you can answer in one screenshot instead of five dashboards. That is a smaller claim than "we make you compliant." It is also the true one.

Checklist: what jurisdiction does not cover in your R2 setup

This is the core of the post. If you take one thing away, take this list. Each item is a place where a reader has assumed the jurisdiction flag protects them and it does not.

Credentials custody. The jurisdiction setting says nothing about where your R2 access keys live. If they're in a .env file on a laptop, in a GitHub Actions secret, in a Notion page someone forgot to delete, or in a third-party SaaS dashboard, the bytes are still EU-pinned but the keys that read them are anywhere. A jurisdiction flag with an exposed token is a locked door with the key taped to it.

Cross-account access. If a partner account, a contractor, or another team in your org has an R2 token scoped to your bucket, their compute and their logs are wherever they are. The jurisdiction on your bucket does not constrain them. It constrains the bucket. Where they call from is their problem, and if the reviewer asks, it becomes yours.

Logs and metadata. R2's access logs, your application logs, your observability pipeline, your error tracking, your analytics. Every one of these is a place where a fragment of the data (a key name, an IP, a user ID, a request body if you log bodies) can end up outside the jurisdiction. The bytes are in the EU. The audit trail might not be. If you have ever pointed your app at a US-based logging SaaS, you have already broken the residency story at the log layer.

Backups and replicas outside the jurisdiction. This is the one that catches people. You pin the bucket to EU. Good. Then your nightly job copies it to a bucket in another account, another jurisdiction, or another provider entirely. Or your replication config points at a non-EU target. Or you have a "cold storage" bucket in a different region that someone set up in 2023 and forgot. The primary is EU. The backup is not. If your DPA covers backups, you have a problem.

CDN edge caching. If you serve objects through a CDN, the object is cached at the edge, and the edge is wherever the user is. Your EU-pinned origin bucket does not stop a copy from sitting on an edge node in Tokyo for the duration of a cache TTL. If your compliance argument covers "data in transit and at rest," cached copies at the edge are a question you need to answer separately. Cloudflare's own cache behaviour is a whole topic; the point here is that the jurisdiction flag on the origin does not control it.

The operator's laptop. The most common residency leak in the wild is a human. Someone in your team pulls the bucket down to their local machine to inspect a file, or runs a sync to a folder, or opens the data in a desktop client that caches a copy in an unsynced location. The jurisdiction is intact. The data is on a laptop in a country you did not plan for. This is not a hypothetical. It is the reason "we have a residency policy" and "we have residency" are different statements.

Here is the checklist in one place, for the reader who wants to copy it into a review doc:

GapCovered by jurisdiction?What you need instead
Primary object bytesYesNothing, this is what the flag does
Credentials custodyNoScoped tokens, rotation policy, secrets manager, or keyless IAM where supported
Cross-account accessNoContract terms, scoped tokens, access review
Logs and metadataNoLog destinations inside the jurisdiction, or a documented exception
Backups and replicasNoAudit every replication target and backup bucket, then pin those too
CDN edge cachingNoCache rules, or a documented position on edge copies
Operator's deviceNoDevice policy, DLP, or a rule that production data does not get pulled locally

Notice that exactly one row is fully covered. That is the honest picture. The flag is necessary and insufficient. If your residency argument rests on it alone, you have a one-line answer to a forty-page questionnaire, and the reviewer will not stop at line one.

Mounting R2 into a container is the request we get and cannot fill

This is the query that keeps showing up: "cloudflare containers r2 fuse mount with s3 credentials from another account." Somebody wants to run a container, mount an R2 bucket as a filesystem inside it, and use credentials that belong to a different account. It is a reasonable thing to want. Here is the honest answer.

Storafleet has no FUSE surface and never will. We are a control plane for object storage. We browse, upload, download, migrate, sync, search, and configure. We do not present a bucket as a directory, and we do not have a mount driver. If the requirement is "a path on disk that is actually R2," we are not the tool, full stop.

What is the tool? The answer is rclone, or one of its cousins.

rclone mount is the standard answer for R2-as-a-filesystem. It uses FUSE on Linux and macOS, it supports R2 as an S3-compatible backend, and it has been the go-to for this exact job for over a decade. You configure a remote with your access key, an endpoint, and a region, then run rclone mount r2:mybucket /mnt/r2 --vfs-cache-mode writes and you have a mount. It works inside containers. It works in systemd units. It composes with everything.

s3fs is the older alternative. It is more finicky, it has historically had more edge cases around consistency and file locking, but it exists and people run it. goofys is the performance-focused option from the same era, less feature-complete, faster on large sequential reads. And of course, a vendor FUSE surface (the kind that commercial products ship) is the "I want a mount and I want a support contract" answer.

On the credentials-from-another-account part: rclone does not care whose account the keys belong to. It takes a key ID, a secret, and an endpoint. If the other account's key is scoped to read your bucket, rclone reads it. If it is not, rclone fails and you fix the scoping. That is the whole mechanism. There is no cross-account magic in the mount layer, and there does not need to be.

We concede this one cleanly. For mounting, rclone is better than us, and it is better than us on every axis that matters: it is open source, it is scriptable, it composes with the rest of your tooling, and it does not require a subscription to exist for the mount to work. It has been maintained for over a decade by people who do this well. If your problem is "I need R2 as a filesystem in my container," the honest response is: go install rclone, write the config, and stop looking at control planes. That is not us being humble. It is us being correct. A FUSE mount is a kernel-level concern and a web console is not a kernel.

What we can do, once the mount is running, is the operational stuff around it: browse the bucket from a UI, run scheduled migrations between providers, search across buckets, pull a cost view, and configure lifecycle and object-lock rules without writing JSON. That is a different layer. If the mount is the only thing you need, you do not need that layer, and we are not going to invent a reason for you to buy one.

Credentials from another account are a policy problem pretending to be a config problem

Cross-account R2 access is solved with Cloudflare's own token scoping, not with a third-party control plane. This is the part where the search query and the real problem diverge.

The query says "S3 credentials from another account." That phrasing suggests the asker thinks the problem is technical: get the right key into the right place. It is not. The problem is: who is allowed to read this bucket, from where, for how long, and how do you prove it was them and not someone else. That is a policy question. The config is downstream of it.

Cloudflare's R2 API tokens can be scoped to specific buckets and specific permission levels (read, write, list, and so on). If you need to give a partner read access to one bucket, you create a token scoped to that bucket with read-only permission. You do not share the account's master credentials. You do not route it through a third party. You do not need a control plane in the middle. You create the token, you hand it over, you note the expiry, you rotate it on schedule. That is the whole solution, and it is a solution you build in Cloudflare's own console.

Where our IAM-role connect applies, and where it does not. Storafleet can connect to AWS without a long-lived access key, using IAM role assumption. That is a genuinely good pattern: no static key sitting in a database, the role can be revoked centrally, and the audit trail lives in AWS CloudTrail. But it is AWS only. R2 does not have the equivalent IAM-role surface in the same way, and we cannot fake one. If you are connecting R2 to Storafleet, you are handing us an R2 API token, encrypted at rest with AES-256-GCM and per-namespace HKDF keys, but still: a token that lives in our database and not on your hardware.

That last sentence is where the honest concession lives. If your security posture requires that credentials never leave hardware you control, our model does not satisfy you. It is not close. The encryption is real and the key handling is real, but the token still transits to our infrastructure and rests there. The alternative that actually satisfies "keys never left my laptop" is rclone, configured with a local config file, running on your machine, talking directly to Cloudflare. The token never leaves your disk. For some teams, that property is worth more than any UI convenience we can offer. We are not going to argue you out of it. If that is your requirement, use rclone and do not look back.

For teams that have decided encrypted-at-rest in a vendor's database is acceptable (most have, whether they have written it down or not), the question becomes: which vendor, under what contract, with what audit rights. That is a procurement conversation. It is not an engineering one, and the jurisdiction flag does not change the answer.

Who should not use Storafleet for this, and what to use instead

We would rather lose the sale honestly than win it and have you churn in three months. Here is who should not buy Storafleet for an R2 residency problem, and what they should use instead.

If your budget is zero, rclone wins. The conversation is over. rclone is a free, open-source tool with no account and no vendor in the loop, and it does everything you need for the R2-as-filesystem or R2-as-scripted-target problem. We are a paid subscription. If the number you have available is zero, no amount of feature comparison changes the arithmetic. Go install rclone.

If you need storage mounted as a filesystem, use rclone mount, Mountain Duck, or ExpanDrive. We have no FUSE surface. We will not have one. A desktop client that mounts is a better tool for a single operator who wants R2 to appear in Finder or Explorer. Mountain Duck and ExpanDrive charge a one-time or annual licence and the files stay on your machine. For one person managing a handful of buckets, that is a better fit than a subscription control plane.

If you need Google Drive, Dropbox, OneDrive, Box, or SFTP, we are the wrong tool. Storafleet connects the S3-compatible family and any custom S3 endpoint, and nothing else. We do not touch the consumer clouds. If the job is Drive-to-bucket, use rclone (it supports 70+ backends including the ones we do not) or MultCloud or CloudFuze, which were built for exactly that. We deliberately do not cover this, and we are not going to pretend otherwise.

If credentials must never leave hardware you control, use rclone, or use our IAM-role connect if it is AWS only. Our model is encrypted credentials in our database. Yours is keys on your disk. Those are different postures and yours is stronger. Do not downgrade it for a UI.

If everything lives in one cloud and always will, that provider's own console is free and more current than we are. If you are all-in on R2 forever, the Cloudflare dashboard is authoritative, always up to date with the newest R2 features, and costs nothing. We exist for the multi-provider and bring-your-own-storage case. If that case is not yours, we are overhead.

If your workflow is entirely code and always will be, a CLI composes and a console does not. We are a web UI. We do not slot into a Makefile. We do not run in a CI step the way a binary does. We do not respond to cron the way rclone sync does. We have scheduled sync as a feature, but the scheduling is a UI feature, not a composable primitive. If your instinct on every problem is "I will write a script," that instinct is correct for you and a CLI is the right tool.

And the one nobody likes to say: we are a small team and Storafleet started in 2026. If your question is "will this vendor still exist in five years," a decade-old open-source project has a better answer than we do. rclone has been maintained for over a decade by a community. It does not go away when a company does. That is a real, material advantage on the "long-term risk" axis, and pretending the comparison is only about features would be dishonest.

So who is Storafleet actually for, on the R2 residency question? The team that has R2 plus at least one other provider, that needs to browse and migrate and search across them from one place, that wants lifecycle and object-lock and CORS config without hand-writing JSON, that has decided encrypted-at-rest credentials in a vendor database are acceptable under a contract they have read, and that values a single pane over a script they have to maintain. That is a real group, and it is not everybody. If you are in it, the jurisdiction flag is one input to a bigger residency argument, and we are one tool in a stack that also includes rclone, a secrets manager, and a device policy. If you are not in it, you now know which tool to reach for, and we would rather you reach for the right one than buy the wrong one.

Your storage estate deserves a control plane.

Join the DevOps teams and founders who run every cloud's buckets from one control plane.

Free plan  ·  No credit card  ·  50+ cloud providers  ·  Cancel any time