Workspace IndexDev Notes › Cloudflare R2 + Workers — cut jurisdiction at the edge, not in the backend

#162PoC

Cloudflare R2 + Workers — cut jurisdiction at the edge, not in the backend

Sanctions and country blocks are enforced where requests arrive, not on-chain — Korea's Polymarket block hit exactly this layer. Cloudflare Workers read request.cf.country before your backend exists to the request, and R2 removes S3's biggest hidden cost (egress fees). Cutting at the edge means the backend never learns about jurisdiction — one enforced, logged boundary instead of policy smeared through the codebase.

Not yet scoped — three measurements when it runs: Latency. Add the country branch in a Worker and measure p50/p99 before and after. The added cost should be under a millisecond — the branch runs in the isolate that was already terminating TLS. If it isn't, something is misarchitected. False positives. Replay a week of real traffic through the geo decision and count VPN exits, satellite links and roaming IPs that land on the wrong side. This number — not the latency — is what decides whether IP-based blocking is defensible alone or only as the first factor in front of KYC. The egress delta. Move the static/data tier to R2 and compare the bill line that S3 never itemizes honestly: egress. The saving is real money at content scale and zero at API scale — measure, don't assume. Source: 09-03 digest, services item — added 2026-09-04.

Why

The principle this implements: jurisdiction logic lives in one access layer, and never in settlement. A geo rule inside business logic multiplies — every endpoint re-implements it, every refactor can drop it, and proving compliance means auditing the whole codebase. The same rule at the edge is one function, running before the origin exists to the request, with one log — and that log is the audit artifact: when a regulator asks "how do you block jurisdiction X," the answer is a file, not a code tour. the-index-is-an-ops-manual made the same move for indices: the product is the accountable boundary, not the logic.

The block point is a fact about how enforcement works, not a design taste. Korea's Polymarket block didn't touch the chain — it hit DNS and the access layer, because that is where a state's writ runs. Sanctions arrive as "do not serve these requests," and only the request path can answer. On-chain is where the card's principle says jurisdiction must not live (jurisdiction-decides-the-category, eighty-percent-is-sports's state-level bans): settlement stays neutral, the boundary absorbs the politics.

And the honest caveat prices the whole design. IP-based country is cheap, fast — and evadable by any VPN, with real false positives. Alone it is not a legal defense; it is the first factor, completed by KYC where stakes demand it. The alternatives (Fastly Compute, CloudFront Functions + paid-egress S3, Deno Deploy) trade on the same axes, and self-hosting halves the point: without edge PoPs there is no "before the backend" to cut at.

How it works

The pieces, and what each replaces

Piece What it is Replaces
Workers V8 isolates running JS/WASM at the edge, request.cf.country built in A geo middleware tier you'd run yourself
R2 S3-compatible object storage, zero egress fees S3's biggest hidden bill line
D1 / KV / Durable Objects / Queues SQLite, key-value, stateful objects, queues in the same runtime A small backend's worth of services

Where the cut happens

export default {
  async fetch(req, env) {
    const country = req.cf.country;               // before the origin exists
    if (env.BLOCKED.split(",").includes(country)) {
      await env.AUDIT.put(crypto.randomUUID(),    // the log IS the audit artifact
        JSON.stringify({ country, url: req.url, t: Date.now() }));
      return new Response("Not available in your region", { status: 451 });
    }
    return fetch(req);                            // backend never learns geography
  }
}

Status 451 ("Unavailable For Legal Reasons") is the honest status code — the block is a legal statement, and the code says so.

Edge cut vs. backend cut

Geo in business logic Geo at the edge
Implementations One per endpoint, drifting One function
Can a refactor drop it Yes, silently No — it's in front of everything
Compliance evidence A codebase audit One log stream
Added latency Varies < 1 ms in the TLS-terminating isolate
Settlement neutrality At risk Preserved by construction

The caveats that complete it

  1. IP → country is evadable (VPN) and errs (satellite, roaming): first factor, not defense.
  2. Pair with KYC where the stakes are legal, not cosmetic.
  3. Measure false positives on real traffic before trusting the boundary.
  4. Alternatives trade the same axes; self-hosting has no edge to cut at.

← All Dev Notes · Workspace Index · Top ↑

Cloudflare R2 + Workers — 법역은 백엔드가 아니라 엣지에서 자른다

제재와 국가 차단은 온체인이 아니라 요청이 도착하는 곳에서 집행됩니다 — 한국의 Polymarket 차단이 때린 곳이 정확히 이 층입니다. Cloudflare Workers 는 백엔드가 요청을 알기도 전에 request.cf.country 를 읽고, R2 는 S3 의 가장 큰 숨은 비용(egress 요금)을 없앱니다. 엣지에서 자르면 백엔드는 법역을 몰라도 됩니다 — 코드베이스 전체에 번진 정책 대신, 집행되고 기록되는 경계 하나.

아직 범위 미정 — 돌릴 때의 측정 셋: 지연. Worker 에 국가 분기를 넣고 전후의 p50/p99 를 측정합니다. 추가 비용은 1ms 미만이어야 합니다 — 분기는 어차피 TLS 를 종단하던 아이솔레이트 안에서 돕니다. 그보다 크면 구조가 잘못된 것입니다. 오탐. 실제 트래픽 일주일치를 지오 판정에 재생해 VPN 출구, 위성 링크, 로밍 IP 가 엉뚱한 쪽에 떨어지는 수를 셉니다. 지연이 아니라 이 숫자가, IP 차단이 단독으로 방어 가능한지 아니면 KYC 앞의 1차 요소로만 유효한지를 결정합니다. Egress 차액. 정적/데이터 계층을 R2 로 옮기고 S3 가 정직하게 항목화하지 않는 청구 줄 — egress — 를 비교합니다. 절감은 콘텐츠 규모에서는 실돈이고 API 규모에서는 0 입니다 — 가정하지 말고 측정하십시오. 출처: 09-03 다이제스트 서비스 항목 — 2026-09-04 추가.

이것이 구현하는 원칙: 법역 로직은 접근 계층 한 곳에 살고, 정산에는 절대 없다. 비즈니스 로직 안의 지오 규칙은 증식합니다 — 엔드포인트마다 재구현되고, 리팩터링마다 빠질 수 있고, 컴플라이언스 증명은 코드베이스 전체 감사가 됩니다. 같은 규칙이 엣지에 있으면 함수 하나, 오리진이 요청을 알기 전에 돌고, 로그 하나 — 그리고 그 로그가 곧 감사 산출물입니다: 규제자가 "X 법역을 어떻게 차단하냐"고 물으면 답이 코드 투어가 아니라 파일입니다. the-index-is-an-ops-manual 이 지수에 대해 한 것과 같은 수: 제품은 로직이 아니라 책임지는 경계입니다.

차단 지점은 설계 취향이 아니라 집행이 작동하는 방식에 대한 사실입니다. 한국의 Polymarket 차단은 체인을 건드리지 않았습니다 — DNS 와 접근 계층을 때렸습니다. 국가의 영장이 미치는 곳이 거기니까. 제재는 "이 요청들을 서비스하지 말라"로 도착하고, 요청 경로만이 답할 수 있습니다. 온체인은 카드의 원칙이 법역이 살면 안 된다고 말하는 곳입니다(jurisdiction-decides-the-category, eighty-percent-is-sports 의 주 단위 금지): 정산은 중립으로 남고, 경계가 정치를 흡수합니다.

그리고 정직한 단서가 설계 전체의 값을 매깁니다. IP 기반 국가 판정은 싸고 빠르지만 — 아무 VPN 으로나 회피되고 오탐이 실재합니다. 단독으로는 법적 방어가 아닙니다; 1차 요소이고, 판돈이 요구하는 곳에서 KYC 로 완결됩니다. 대안들(Fastly Compute, CloudFront Functions + 유료 egress S3, Deno Deploy)은 같은 축에서 트레이드하고, 셀프 호스팅은 의미가 반감됩니다: 엣지 PoP 이 없으면 잘라 낼 "백엔드 이전"이 존재하지 않습니다.

동작 방식

부품들, 각각 무엇을 대체하나

부품 무엇인가 대체하는 것
Workers 엣지에서 JS/WASM 을 돌리는 V8 아이솔레이트, request.cf.country 내장 직접 돌릴 지오 미들웨어 계층
R2 S3 호환 오브젝트 스토리지, egress 무료 S3 의 가장 큰 숨은 청구 줄
D1 / KV / Durable Objects / Queues 같은 런타임의 SQLite·키밸류·상태 객체·큐 작은 백엔드 하나 분량의 서비스

자르는 지점

export default {
  async fetch(req, env) {
    const country = req.cf.country;               // 오리진이 알기 전에
    if (env.BLOCKED.split(&quot;,&quot;).includes(country)) {
      await env.AUDIT.put(crypto.randomUUID(),    // 이 로그가 곧 감사 산출물
        JSON.stringify({ country, url: req.url, t: Date.now() }));
      return new Response(&quot;Not available in your region&quot;, { status: 451 });
    }
    return fetch(req);                            // 백엔드는 지리를 끝내 모른다
  }
}

상태 코드 451("Unavailable For Legal Reasons")이 정직한 코드입니다 — 차단은 법적 진술이고, 코드가 그렇게 말합니다.

엣지 컷 대 백엔드 컷

비즈니스 로직 속 지오 엣지의 지오
구현 수 엔드포인트마다 하나, 표류함 함수 하나
리팩터링이 떨굴 수 있나 예, 조용히 아니오 — 모든 것 앞에 있음
컴플라이언스 증거 코드베이스 감사 로그 스트림 하나
추가 지연 제각각 TLS 종단 아이솔레이트 안에서 < 1ms
정산 중립성 위험 구조적으로 보존

완결짓는 단서들

  1. IP → 국가는 회피 가능(VPN)하고 오류(위성·로밍)가 있다: 1차 요소이지 방어가 아니다.
  2. 판돈이 법적인 곳에서는 KYC 와 짝지을 것.
  3. 경계를 믿기 전에 실제 트래픽으로 오탐률을 잴 것.
  4. 대안들은 같은 축의 트레이드; 셀프 호스팅에는 잘라 낼 엣지가 없다.

← 전체 개발 노트 · 워크스페이스 인덱스 · 맨 위 ↑