Pikku Cloudflare Workers Runtime
This skill helps you deploy Pikku functions to Cloudflare Workers for edge computing.
When to use this skillβ
- Edge computing (code runs close to users globally)
- Ultra-low latency (< 50ms worldwide)
- Pay-per-request pricing (10M requests free per day)
- Auto-scaling (0 to millions instantly)
- No cold starts (Workers start in < 1ms)
- Global distribution (deployed to 300+ cities)
- WebSocket support with Durable Objects
- Integration with Cloudflare services (KV, R2, D1, etc.)
Performance: Cloudflare Workers run on V8 isolates (not containers), resulting in near-instant startup and low memory overhead.
Quick Setupβ
Prerequisites: See pikku-project-setup for project structure detection and common setup patterns.
1. Install Packagesβ
npm install @pikku/cloudflare @pikku/core
npm install -D wrangler @cloudflare/workers-types typescript
2. Create Worker Fileβ
Standalone: Create src/index.ts
based on templates/cloudflare-workers/src/index.ts
Workspace: Create src/index.ts
based on workspace-starter/backends/cloudflare/src/index.ts
Key imports:
- Import bootstrap (see pikku-project-setup for correct path)
- Import
runFetch
andrunScheduled
from@pikku/cloudflare
- Import setup functions and services
- Export default object with
fetch
andscheduled
handlers
3. Configure wrangler.tomlβ
Create wrangler.toml
with:
- Worker name and main entry point
- Compatibility flags (nodejs_compat)
- Environment variables and bindings
- Routes and triggers
Template: templates/cloudflare-workers/wrangler.toml
Critical: Enable nodejs_compat
for Node.js built-ins.
4. Setup Services from Envβ
const localVariables = new LocalVariablesService(env)
const config = await createConfig(localVariables)
const localSecrets = new LocalSecretService(localVariables)
const singletonServices = await createSingletonServices(config, {
secrets: localSecrets,
})
Note: No cold start caching needed (Workers start in < 1ms).
5. Update Package.json Scriptsβ
{
"scripts": {
"pikku": "pikku all",
"prebuild": "npm run pikku",
"dev": "wrangler dev",
"deploy": "wrangler deploy"
}
}
6. Generate & Verifyβ
# Generate wiring (if applicable to your project type)
npm run pikku
# Start local development with wrangler
npm run dev
# Verify endpoint
curl http://localhost:8787/your-endpoint
Expected outcome: Wrangler dev starts local worker, endpoints respond correctly, near-instant startup times.
Installationβ
npm install @pikku/cloudflare @pikku/core
npm install -D wrangler @cloudflare/workers-types typescript
Setupβ
Standalone Projectβ
For standalone projects where functions are in the same package.
Example: templates/cloudflare-workers/src/index.ts
Key points:
- Import bootstrap from local
./.pikku/pikku-bootstrap.gen.js
- Import services from local files
- Export default object with
fetch
andscheduled
handlers - Use
setupServices
to initialize services from env - Configure
wrangler.toml
for deployment
Workspace - No Backend Config (Simpler)β
Backend imports functions from the functions package.
Example: workspace-starter/backends/cloudflare/src/index.ts
Key differences:
- Import config/services from functions package:
@my-app/functions/src/services
- Import bootstrap from functions:
@my-app/functions/.pikku/pikku-bootstrap.gen
- No
pikku
script needed in backend package.json - Uses functions package filters
Tradeoffs:
- β Faster: No extra build step per backend
- β Simpler: One source of truth
- β Can't customize filtering (uses functions package filters)
Workspace - With Backend Config (Filtered)β
Backend has its own pikku.config.json
with custom filters.
Backend pikku.config.json:
{
"extends": "../../packages/functions/pikku.config.json",
"filters": {
"types": ["http", "scheduler"],
"tags": ["api", "edge"],
"excludeTags": ["server-only", "websocket"]
}
}
Bootstrap import:
// Import from backend's .pikku directory (custom filters)
import '../.pikku/pikku-bootstrap.gen'
Build process:
cd backends/cloudflare
yarn pikku
(reads local pikku.config.json, applies custom filters)- Generated files in
backends/cloudflare/.pikku/
include only filtered functions
Tradeoffs:
- β Custom filtering: Different API subsets per backend
- β Tree-shaking: Better bundle size per backend
- β Runtime-specific: Exclude incompatible functions per backend
- β Slower: Must run
pikku
per backend
Handler Typesβ
HTTP Fetch Handlerβ
Handle HTTP requests at the edge.
Pattern:
import { runFetch } from '@pikku/cloudflare'
import { setupServices } from './setup-services.js'
import { createSessionServices } from './services.js'
import { ExportedHandler, Response } from '@cloudflare/workers-types'
import './.pikku/pikku-bootstrap.gen.js'
export default {
async fetch(request, env): Promise<Response> {
const singletonServices = await setupServices(env)
return await runFetch(
request as unknown as Request,
singletonServices,
createSessionServices
)
},
} satisfies ExportedHandler<Record<string, string>>
See: templates/cloudflare-workers/src/index.ts
Scheduled Tasksβ
Handle cron triggers.
Pattern:
import { runScheduled } from '@pikku/cloudflare'
import { setupServices } from './setup-services.js'
import { ExportedHandler } from '@cloudflare/workers-types'
export default {
async scheduled(controller, env) {
const singletonServices = await setupServices(env)
await runScheduled(controller, singletonServices)
},
} satisfies ExportedHandler<Record<string, string>>
Configure cron in wrangler.toml:
[triggers]
crons = ["0 0 * * *"] # Daily at midnight UTC
Service Setupβ
Services are initialized from Cloudflare environment variables.
Pattern:
import { LocalVariablesService, LocalSecretService } from '@pikku/core/services'
import { createConfig, createSingletonServices } from './services.js'
export const setupServices = async (
env: Record<string, string | undefined>
) => {
const localVariables = new LocalVariablesService(env)
const config = await createConfig(localVariables)
const localSecrets = new LocalSecretService(localVariables)
return await createSingletonServices(config, {
variables: localVariables,
secrets: localSecrets,
})
}
Key points:
LocalVariablesService
: Reads from Cloudflare env varsLocalSecretService
: Reads secrets from env vars (set via wrangler)- No cold start caching needed (Workers are fast)
See: templates/cloudflare-workers/src/setup-services.ts
WebSocket Supportβ
Cloudflare Workers support WebSockets via Durable Objects with hibernation.
Example: templates/cloudflare-websocket/src/websocket-hibernation-server.ts
Pattern:
import { CloudflareWebSocketHibernationServer } from '@pikku/cloudflare'
import { CloudflareEventHubService } from '@pikku/cloudflare'
import { setupServices } from './setup-services.js'
import { createSessionServices } from './services.js'
export class WebSocketHibernationServer extends CloudflareWebSocketHibernationServer {
private singletonServices: SingletonServices | undefined
protected async getParams() {
if (!this.singletonServices) {
this.singletonServices = await setupServices(this.env)
this.singletonServices.eventHub = new CloudflareEventHubService(
this.singletonServices.logger,
this.ctx
)
}
return {
singletonServices: this.singletonServices,
createSessionServices,
}
}
}
Key points:
- Extends
CloudflareWebSocketHibernationServer
- Uses
CloudflareEventHubService
for WebSocket management - Hibernation reduces memory usage when connections are idle
- Requires Durable Objects (paid plan)
WebSocket examples:
Wrangler Configurationβ
wrangler.toml:
#:schema node_modules/wrangler/config-schema.json
name = "my-pikku-app"
main = "src/index.ts"
compatibility_date = "2024-12-18"
compatibility_flags = ["nodejs_compat_v2"]
[observability]
enabled = true
[vars]
NODE_ENV = "production"
[triggers]
crons = ["0 0 * * *"]
Key settings:
main
: Entry point file (Wrangler compiles TypeScript automatically)compatibility_date
: Cloudflare Workers API versioncompatibility_flags
: Enable Node.js compatibility[vars]
: Environment variables[triggers]
: Cron schedules
Secrets: Set via wrangler CLI (not in wrangler.toml):
wrangler secret put DATABASE_URL
wrangler secret put JWT_SECRET
See: templates/cloudflare-workers/wrangler.toml
Developmentβ
Scriptsβ
Standalone:
{
"scripts": {
"pikku": "pikku all",
"prebuild": "npm run pikku",
"dev": "wrangler dev",
"start": "wrangler dev",
"deploy": "wrangler deploy"
}
}
Workspace (no backend config):
{
"scripts": {
"dev": "wrangler dev",
"start": "wrangler dev",
"deploy": "wrangler deploy"
}
}
Workspace (with backend config):
{
"scripts": {
"pikku": "pikku",
"prebuild": "npm run pikku",
"dev": "wrangler dev",
"start": "wrangler dev",
"deploy": "wrangler deploy"
}
}
Local Developmentβ
Use wrangler dev
to test Workers locally:
npm run dev
# Server runs at http://localhost:8787
Features:
- Hot reload on file changes
- Local environment variables
- Simulates edge runtime locally
- Access to local KV, R2, D1 (if configured)
Deploymentβ
Deploy to Cloudflare Workers:
# Deploy to production
wrangler deploy
# Deploy to specific environment
wrangler deploy --env staging
# View logs
wrangler tail
# Set secrets
wrangler secret put DATABASE_URL
# List deployments
wrangler deployments list
Authentication: Login to Cloudflare:
wrangler login
Custom domains: Configure in Cloudflare Dashboard β Workers & Pages β your worker β Settings β Triggers β Custom Domains
Performance Tipsβ
- No bundler needed: Wrangler compiles TypeScript automatically
- Tree-shaking: Unused code is removed automatically
- CPU limits: Workers have 50ms CPU time limit (10ms on free plan)
- Memory limits: 128MB memory limit
- Subrequests: Max 50 subrequests per Worker invocation
- Durable Objects: Use for stateful WebSocket connections
- KV storage: Use for read-heavy data (eventually consistent)
- R2 storage: Use for large files (S3-compatible)
- D1 database: Use for relational data (SQLite at edge)
Examplesβ
Standalone:
- templates/cloudflare-workers - HTTP + cron
- templates/cloudflare-websocket - WebSocket with Durable Objects
Workspace:
- workspace-starter/backends/cloudflare - Workspace HTTP backend
- workspace-starter/backends/cloudflare-websocket - Workspace WebSocket backend
Critical Rulesβ
Standalone Projectsβ
- Import bootstrap from local:
'./.pikku/pikku-bootstrap.gen.js'
- Import services from local files:
'./services.js'
- Export default object with
fetch
and/orscheduled
handlers - Use
LocalVariablesService
andLocalSecretService
- Configure
wrangler.toml
with compatibility flags
Workspace (No Backend Config)β
- Import config/services from functions:
'@my-app/functions/src/...'
- Import bootstrap from functions:
'@my-app/functions/.pikku/pikku-bootstrap.gen'
- Backend package.json has
"@my-app/functions": "workspace:*"
- No
pikku
script needed
Workspace (With Backend Config)β
- Backend has
pikku.config.json
withextends
- Import bootstrap from backend:
'../.pikku/pikku-bootstrap.gen'
- Backend package.json includes
"pikku": "pikku"
script - Backend package.json includes
"@pikku/cli"
in devDependencies - Run
pikku
in backend directory to generate filtered wiring
Configurationβ
- Set
compatibility_flags = ["nodejs_compat_v2"]
in wrangler.toml - Use
wrangler secret put
for sensitive values (not wrangler.toml) - Configure cron triggers in
[triggers]
section - Enable observability for production monitoring
WebSocketβ
- Extend
CloudflareWebSocketHibernationServer
- Use
CloudflareEventHubService
for WebSocket management - Requires Durable Objects (paid Cloudflare plan)
- Configure Durable Object bindings in wrangler.toml
Deploymentβ
- Run
wrangler login
to authenticate - Use
wrangler deploy
to deploy - Set secrets via
wrangler secret put
- Monitor with
wrangler tail
- Configure custom domains in Cloudflare Dashboard
Performanceβ
- Stay within 50ms CPU time limit
- Use KV for read-heavy data
- Use R2 for large file storage
- Use D1 for relational data at edge
- Limit subrequests to 50 per invocation
Related Skillsβ
Prerequisites:
- pikku-project-setup - Project structure and common setup patterns
- pikku-functions - Creating Pikku function definitions
Wiring:
- pikku-http - HTTP route wiring and configuration
- pikku-scheduler - Scheduled task configuration
- pikku-channel - WebSocket/channel wiring (with Durable Objects)
Alternative Runtimes:
- pikku-aws-lambda - Serverless alternative
- pikku-express - Traditional server deployment
- pikku-fastify - Traditional server deployment