Skip to content

Cloudflare

Cloudflare is a global network and edge-cloud platform.

Electric and Cloudflare

You can use Cloudflare as a CDN in front of Electric and as a sync target to sync data into Cloudflare primitives including Workers and Durable Objects.

Need context?

See the Deployment guide for more details.

CDN

Cloudflare provides a global content delivery network.

This guide walks through the process of using it. Basically you need to create a DNS rule resolving to the Electric service and enable Cloudflare as a proxy for it.

Electric's HTTP API caching will work out of the box.

Workers

You can also use Cloudflare Workers in front of the CDN to handle concerns like authorization and routing.

Auth example

For example, you could validate an auth token to protect access to a shape and then proxy the request through to Electric:

ts
export default {
  async fetch(request): Promise<Response> {
    const ELECTRIC_URL = 'https://my-electric.example.com'

    const headers = request.headers
    const authHeader = request.headers.get('Authorization')
    const isValid = (header) => { /* ... e.g.: verify JWT ... */ }
    if (!isValid(authHeader)) {
      return new Response('Forbidden', {status: 403})
    }

    if (request.method != `GET`) {
      return new Response('Method Not Allowed', {status: 405})
    }

    const url = new URL(request.url)
    const shapeUrl = `${ELECTRIC_URL}${url.pathname}${url.search}`
    const clonedHeaders = new Headers(new Request(request).headers)

    return await fetch(
      shapeUrl, {
        headers: clonedHeaders,
        cf: { cacheEverything: true }
      }
    )
  },
} satisfies ExportedHandler;

Syncing data into the worker

Or you can use Electric to hydrate data quickly into an edge worker. For example, you could sync data into an edge worker to dynamically redirect the request:

ts
import { ShapeStream, Shape } from '@electric-sql/client'

export default {
  async fetch(request): Promise<Response> {
    const ELECTRIC_URL = 'https://my-electric.example.com'

    const stream = new ShapeStream({
      url: `${ELECTRIC_URL}/v1/shape`,
      params: {
        table: 'routes'
      }
    })
    const shape = new Shape(stream)
    const routes = await shape.value

    const url = new URL(request.url)
    const match = routes.find(x => x.path == url.pathname)

    if (!match) {
      return new Response('Not Found', {status: 404})
    }

    return Response.redirect(match.redirect, 301)
  },
} satisfies ExportedHandler;

Durable Objects

You can implement a similar pattern to the sync example above to sync data into a Durable Object.

The key difference is that with a Durable Object, the data can be persisted across requests. This allows you to sync a shape log into the Durable Object, materialise the shape into persistent storage and then re-sync the latest changes whenever the Durable Object is accessed.

You can see a demo of this pattern, using SQLite to persist the Shape data, at KyleAMathews/electric-demo-cloudflare-sqlite:

Combining CDN and Durable Objects

Note that if you sync data into a Durable Object (or a Worker) from Cloudflare's CDN it can be extremely fast — with high bandwidth and low network latency.

Help wanted Good first issue

We have an open GitHub issue tracking this if you'd like to contribute example apps using Cloudflare and/or wrap up the code samples above into a library.

Please leave a comment or ask on Discord if you'd like any pointers or to discuss how best to approach this.