mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 06:11:27 -07:00
184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
# Smart Placement API
|
|
|
|
## Placement Status API
|
|
|
|
Query Worker placement status via Cloudflare API:
|
|
|
|
```bash
|
|
curl -X GET "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/workers/services/{WORKER_NAME}" \
|
|
-H "Authorization: Bearer <TOKEN>" \
|
|
-H "Content-Type: application/json"
|
|
```
|
|
|
|
Response includes `placement_status` field:
|
|
|
|
```typescript
|
|
type PlacementStatus =
|
|
| undefined // Not yet analyzed
|
|
| 'SUCCESS' // Successfully optimized
|
|
| 'INSUFFICIENT_INVOCATIONS' // Not enough traffic
|
|
| 'UNSUPPORTED_APPLICATION'; // Made Worker slower (reverted)
|
|
```
|
|
|
|
## Status Meanings
|
|
|
|
**`undefined` (not present)**
|
|
- Worker not yet analyzed
|
|
- Always runs at default edge location closest to user
|
|
|
|
**`SUCCESS`**
|
|
- Analysis complete, Smart Placement active
|
|
- Worker runs in optimal location (may be edge or remote)
|
|
|
|
**`INSUFFICIENT_INVOCATIONS`**
|
|
- Not enough requests to make placement decision
|
|
- Requires consistent multi-region traffic
|
|
- Always runs at default edge location
|
|
|
|
**`UNSUPPORTED_APPLICATION`** (rare, <1% of Workers)
|
|
- Smart Placement made Worker slower
|
|
- Placement decision reverted
|
|
- Always runs at edge location
|
|
- Won't be re-analyzed until redeployed
|
|
|
|
## cf-placement Header (Beta)
|
|
|
|
Smart Placement adds response header indicating routing decision:
|
|
|
|
```typescript
|
|
// Remote placement (Smart Placement routed request)
|
|
"cf-placement: remote-LHR" // Routed to London
|
|
|
|
// Local placement (default edge routing)
|
|
"cf-placement: local-EWR" // Stayed at Newark edge
|
|
```
|
|
|
|
Format: `{placement-type}-{IATA-code}`
|
|
- `remote-*` = Smart Placement routed to remote location
|
|
- `local-*` = Stayed at default edge location
|
|
- IATA code = nearest airport to data center
|
|
|
|
**Warning:** Beta feature, may be removed before GA.
|
|
|
|
## Detecting Smart Placement in Code
|
|
|
|
**Note:** `cf-placement` header is a beta feature and may change or be removed.
|
|
|
|
```typescript
|
|
export default {
|
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
const placementHeader = request.headers.get('cf-placement');
|
|
|
|
if (placementHeader?.startsWith('remote-')) {
|
|
const location = placementHeader.split('-')[1];
|
|
console.log(`Smart Placement routed to ${location}`);
|
|
} else if (placementHeader?.startsWith('local-')) {
|
|
const location = placementHeader.split('-')[1];
|
|
console.log(`Running at edge location ${location}`);
|
|
}
|
|
|
|
return new Response('OK');
|
|
}
|
|
} satisfies ExportedHandler<Env>;
|
|
```
|
|
|
|
## Request Duration Metrics
|
|
|
|
Available in Cloudflare dashboard when Smart Placement enabled:
|
|
|
|
**Workers & Pages → [Your Worker] → Metrics → Request Duration**
|
|
|
|
Shows histogram comparing:
|
|
- Request duration WITH Smart Placement (99% of traffic)
|
|
- Request duration WITHOUT Smart Placement (1% baseline)
|
|
|
|
**Request Duration vs Execution Duration:**
|
|
- **Request duration:** Total time from request arrival to response delivery (includes network latency)
|
|
- **Execution duration:** Time Worker code actively executing (excludes network waits)
|
|
|
|
Use request duration to measure Smart Placement impact.
|
|
|
|
### Interpreting Metrics
|
|
|
|
| Metric Comparison | Interpretation | Action |
|
|
|-------------------|----------------|--------|
|
|
| WITH < WITHOUT | Smart Placement helping | Keep enabled |
|
|
| WITH ≈ WITHOUT | Neutral impact | Consider disabling to free resources |
|
|
| WITH > WITHOUT | Smart Placement hurting | Disable with `mode: "off"` |
|
|
|
|
**Why Smart Placement might hurt performance:**
|
|
- Worker primarily serves static assets or cached content
|
|
- Backend services are globally distributed (no single optimal location)
|
|
- Worker has minimal backend communication
|
|
- Using Pages with `assets.run_worker_first = true`
|
|
|
|
**Typical improvements when Smart Placement helps:**
|
|
- 20-50% reduction in request duration for database-heavy Workers
|
|
- 30-60% reduction for Workers making multiple backend API calls
|
|
- Larger improvements when backend is geographically concentrated
|
|
|
|
## Monitoring Commands
|
|
|
|
```bash
|
|
# Tail Worker logs
|
|
wrangler tail your-worker-name
|
|
|
|
# Tail with filters
|
|
wrangler tail your-worker-name --status error
|
|
wrangler tail your-worker-name --header cf-placement
|
|
|
|
# Check placement status via API
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/services/$WORKER_NAME \
|
|
| jq .result.placement_status
|
|
```
|
|
|
|
## TypeScript Types
|
|
|
|
```typescript
|
|
// Placement status returned by API (field may be absent)
|
|
type PlacementStatus =
|
|
| 'SUCCESS'
|
|
| 'INSUFFICIENT_INVOCATIONS'
|
|
| 'UNSUPPORTED_APPLICATION'
|
|
| undefined;
|
|
|
|
// Placement configuration in wrangler.jsonc
|
|
type PlacementMode = 'smart' | 'off';
|
|
|
|
interface PlacementConfig {
|
|
mode: PlacementMode;
|
|
// Legacy fields (deprecated/removed):
|
|
// hint?: string; // REMOVED - no longer supported
|
|
}
|
|
|
|
// Explicit placement (separate feature from Smart Placement)
|
|
interface ExplicitPlacementConfig {
|
|
region?: string;
|
|
host?: string;
|
|
hostname?: string;
|
|
// Cannot combine with mode field
|
|
}
|
|
|
|
// Worker metadata from API response
|
|
interface WorkerMetadata {
|
|
placement?: PlacementConfig | ExplicitPlacementConfig;
|
|
placement_status?: PlacementStatus;
|
|
}
|
|
|
|
// Service Binding for backend Worker
|
|
interface Env {
|
|
BACKEND_SERVICE: Fetcher; // Service Binding to backend Worker
|
|
DATABASE: D1Database;
|
|
}
|
|
|
|
// Example Worker with Service Binding
|
|
export default {
|
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
// Forward to backend Worker with Smart Placement enabled
|
|
const response = await env.BACKEND_SERVICE.fetch(request);
|
|
return response;
|
|
}
|
|
} satisfies ExportedHandler<Env>;
|
|
```
|