# Multi-PoP Latency Map (/docs/experiments/multi-pop-latency-map)



Fetch a target URL from the edge and report response time plus the **Cloudflare colo** (`cf.colo`) that handled the Worker invocation. Documents honestly that each request runs in a **single PoP** - not a global multi-region sweep.

## Features [#features]

* **GET /latency?url=** - Response time, status code, and edge location
* **Colo metadata** - `colo`, `city`, `country` from `request.cf`
* **Transparent limitations** - Response includes `limitation` and `tip` fields
* **Cache bypass** - Uses `cf: { cacheTtl: 0 }` on the outbound fetch

## API Reference [#api-reference]

### GET /latency [#get-latency]

Measure fetch latency from the current edge location.

<TypeTable
  type="{
  url: {
    description: &#x22;Target URL (http or https only).&#x22;,
    type: &#x22;string&#x22;,
    required: true,
  },
}"
/>

#### Example Request [#example-request]

```bash
curl "https://your-worker.workers.dev/latency?url=https://www.cloudflare.com"
```

#### Success Response [#success-response]

```json
{
  "url": "https://www.cloudflare.com/",
  "responseTimeMs": 87,
  "statusCode": 200,
  "colo": "SFO",
  "city": "San Francisco",
  "country": "US",
  "timestamp": "2025-06-20T12:00:00.000Z",
  "limitation": "Each Worker invocation runs in a single Cloudflare PoP...",
  "tip": "For multi-region comparison, call this endpoint repeatedly from different client locations..."
}
```

#### Error Codes [#error-codes]

* `400` - Invalid URL (`INVALID_URL`)
* `502` - Fetch failed (`FETCH_ERROR`)

<Callout type="warning">
  This endpoint reports latency from **one PoP per request**. It does not perform a simultaneous multi-region ping. Call repeatedly from different geographic clients to compare colos.
</Callout>

## Use Cases [#use-cases]

* Show students how `request.cf.colo` identifies the serving edge
* Compare latency when calling the worker from different client locations
* Learn honest edge networking constraints in Workers

## Limitations [#limitations]

* Single PoP per invocation; no built-in multi-region orchestration
* `colo` reflects where the Worker ran, not every hop to the origin
* Outbound fetch timing includes DNS + TLS + TTFB for the target URL

## Deployment [#deployment]

<Steps>
  <Step>
    ### Click the deploy button [#click-the-deploy-button]

    [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/shrinathsnayak/cloudflare-experiments/tree/main/apps/experiments/multi-pop-latency-map)
  </Step>

  <Step>
    ### Test your deployment [#test-your-deployment]

    ```bash
    curl "https://your-worker.workers.dev/latency?url=https://example.com"
    ```
  </Step>
</Steps>

## Local Development [#local-development]

```bash
cd apps/experiments/multi-pop-latency-map
npm install
npm run dev
```

<Callout>
  `colo` and geolocation fields are populated when deployed to Cloudflare's edge. Local `wrangler dev` may return null for some `cf` properties.
</Callout>

## Cloudflare Features Used [#cloudflare-features-used]

* **[Workers](https://developers.cloudflare.com/workers/)** - Edge compute runtime
* **`request.cf`** - Colo and geolocation metadata
* **Fetch API** - Outbound HTTP with cache controls
