Pulse 1.0.0-beta.1 betaExact, immutable release documentation.Browse latest
Documentation platform maintainersactiveReviewed 2026-08-01Review by 2027-01-12

Fetching and composing data#

ctx.fetch is the primary host effect for data workflows.

One project, three composition forms#

import { Pulse } from '@pulse-compute/pulse'

interface User {
  id: number
  name: string
}

interface Stats {
  score: number
}

interface Flags {
  enabled: boolean
}

const app = new Pulse({ auto: true })

// One structured origin.
app.get('/user', async (ctx) => {
  const user = await ctx
    .fetch('https://users.example.test/users/123')
    .json<User>()
  return ctx.json({ found: true, user })
})

// Multiple origins with explicit sequential awaits.
app.get('/user-summary', async (ctx) => {
  const user = await ctx
    .fetch('https://users.example.test/users/123')
    .json<User>()
  const stats = await ctx
    .fetch('https://stats.example.test/users/123')
    .json<Stats>()
  const flags = await ctx
    .fetch('https://flags.example.test/users/123')
    .json<Flags>()
  return ctx.json({
    id: user.id,
    name: user.name,
    score: stats.score,
    enabled: flags.enabled,
  })
})

// Multiple origins with explicit portable concurrency.
app.get('/user-summary-parallel', async (ctx) => {
  const { user, stats, flags } = await ctx.parallel({
    user: ctx.fetch('https://users.example.test/users/123').json<User>(),
    stats: ctx.fetch('https://stats.example.test/users/123').json<Stats>(),
    flags: ctx.fetch('https://flags.example.test/users/123').json<Flags>(),
  })
  return ctx.json({
    id: user.id,
    name: user.name,
    score: stats.score,
    enabled: flags.enabled,
  })
})

export default app

The comments separate one structured origin, explicit sequential composition, and ctx.parallel. Separate awaits retain sequential JavaScript semantics. The explicit keyed group is the portable concurrency contract across JavaScript and Native targets. Results retain their source keys even when hosts resolve the operations in another order.

HTTP 404 and 500 remain ordinary response data. DNS, connection, timeout, and host failures fail the effect.

Dependent requests#

A request whose URL or options depend on a previous result lowers to a later continuation point. The compiler does not pretend that dependent effects are an independent group.

Pass-through#

import { Pulse } from '@pulse-compute/pulse'

const app = new Pulse({ auto: true })

app.get('/archive', async (ctx) => {
  return ctx.fetch('https://assets.example.com/archive.bin')
})

export default app

The direct response path preserves status, headers, repeated headers, and the host-owned body. User code cannot inspect or transform the opaque body.

Browse other documentation