Skip to main content
The @feathersjs/koa package provides integration between Feathers and Koa, bringing async/await middleware patterns and lightweight HTTP handling to your Feathers services.

Installation

npm install @feathersjs/koa koa

Basic Setup

1

Create the Koa application

The Koa integration wraps a Feathers application with Koa functionality:
import { feathers } from '@feathersjs/feathers'
import { koa } from '@feathersjs/koa'

const app = koa(feathers())
2

Add body parsing middleware

Enable request body parsing for POST/PUT/PATCH requests:
import { bodyParser } from '@feathersjs/koa'

app.use(bodyParser())
3

Configure REST transport

Enable the REST transport to expose services via HTTP:
import { rest } from '@feathersjs/koa'

app.configure(rest())
4

Register services

Services are automatically exposed as REST endpoints:
app.use('/users', {
  async find() {
    return [{ id: 1, name: 'Alice' }]
  },
  async get(id) {
    return { id, name: 'Alice' }
  }
})
5

Add error handling

Use the error handler middleware to catch and format errors:
import { errorHandler } from '@feathersjs/koa'

app.use(errorHandler())
6

Start the server

The listen method automatically calls setup() on all services:
await app.listen(3030)
console.log('Feathers app started on http://localhost:3030')

Complete Example

import { feathers } from '@feathersjs/feathers'
import { koa, rest, bodyParser, errorHandler, cors } from '@feathersjs/koa'

const app = koa(feathers())

// Middleware must be added before REST configuration
app.use(errorHandler())
app.use(cors())
app.use(bodyParser())

// Configure REST transport
app.configure(rest())

// Register services
app.use('/messages', {
  async find() {
    return [
      { id: 1, text: 'Hello world' },
      { id: 2, text: 'How are you?' }
    ]
  },
  async create(data) {
    return { id: 3, ...data }
  }
})

// Custom Koa middleware
app.use(async (ctx, next) => {
  if (ctx.path === '/health') {
    ctx.body = { status: 'ok' }
  } else {
    await next()
  }
})

// Start server
const server = await app.listen(3030)
console.log('Server ready on http://localhost:3030')

Service Middleware

Koa middleware can be added before and after service calls using the koa option:
import { Middleware } from '@feathersjs/koa'

const logRequest: Middleware = async (ctx, next) => {
  console.log(`${ctx.method} ${ctx.path}`)
  await next()
}

const addTimestamp: Middleware = async (ctx, next) => {
  await next()
  ctx.body = { ...ctx.body, timestamp: new Date() }
}

app.use('/todos', todoService, {
  koa: {
    before: [logRequest],
    after: [addTimestamp]
  },
  methods: ['find', 'get', 'create']
})

Middleware Patterns

Middleware in the before array runs before the service method:
const validateRequest: Middleware = async (ctx, next) => {
  if (!ctx.request.headers.authorization) {
    ctx.throw(401, 'Unauthorized')
  }
  await next()
}

app.use('/protected', service, {
  koa: {
    before: [validateRequest]
  }
})

Context and Feathers Params

Koa’s ctx.feathers object contains Feathers-specific parameters:
app.use(async (ctx, next) => {
  // Access Feathers params
  console.log(ctx.feathers.provider)  // 'rest'
  console.log(ctx.feathers.headers)   // Request headers

  // Add custom params that services will receive
  ctx.feathers.customData = { userId: 123 }

  await next()
})

app.use('/items', {
  async find(params) {
    // params includes ctx.feathers properties
    console.log(params.customData)  // { userId: 123 }
    console.log(params.provider)     // 'rest'
    return []
  }
})

Authentication

Integrate Feathers authentication with Koa middleware:
import { authenticate } from '@feathersjs/koa'

// Protect routes with authentication
app.use('/admin', authenticate('jwt'), adminService)

// Authentication middleware
const requireAuth: Middleware = authenticate('jwt')

app.use(async (ctx, next) => {
  if (ctx.path.startsWith('/api/')) {
    await requireAuth(ctx, next)
  } else {
    await next()
  }
})

Authentication Configuration

import { rest, parseAuthentication } from '@feathersjs/koa'

// Configure REST with automatic authentication parsing
app.configure(rest({
  authentication: {
    service: 'authentication',
    strategies: ['jwt', 'local']
  }
}))

// Or add authentication parsing globally
app.use(parseAuthentication({
  service: 'authentication',
  strategies: ['jwt']
}))

Error Handling

Koa error handling is done through middleware:
import { errorHandler } from '@feathersjs/koa'

// Use default error handler (must be first middleware)
app.use(errorHandler())
app.use(bodyParser())
app.configure(rest())

Static Files

Serve static files using Koa’s static middleware:
import { serveStatic } from '@feathersjs/koa'
import path from 'path'

// Serve static files from public directory
app.use(serveStatic(path.join(__dirname, 'public')))

// Serve with options
app.use(serveStatic('assets', {
  maxage: 86400000, // 1 day
  hidden: false
}))

Custom Response Formatting

Customize how service results are sent as HTTP responses:
import { rest, Middleware } from '@feathersjs/koa'

const customFormatter: Middleware = async (ctx, next) => {
  await next()

  // Wrap all responses
  if (ctx.body) {
    ctx.body = {
      success: true,
      result: ctx.body,
      timestamp: Date.now()
    }
  }
}

app.configure(rest({ formatter: customFormatter }))

Using Existing Koa App

Integrate Feathers into an existing Koa application:
import Koa from 'koa'
import { koa as feathersKoa } from '@feathersjs/koa'
import { feathers } from '@feathersjs/feathers'

// Existing Koa app
const koaApp = new Koa()
koaApp.use(async (ctx, next) => {
  if (ctx.path === '/health') {
    ctx.body = { status: 'ok' }
  } else {
    await next()
  }
})

// Add Feathers to it
const app = feathersKoa(feathers(), koaApp)
app.configure(rest())
app.use('/api/users', userService)

await app.listen(3030)

Pure Koa Middleware

You can mix Feathers services with pure Koa middleware:
import { koa, rest, bodyParser } from '@feathersjs/koa'
import Router from '@koa/router'

const app = koa(feathers())
app.use(bodyParser())

// Use Koa router
const router = new Router()
router.get('/status', (ctx) => {
  ctx.body = { status: 'ok', uptime: process.uptime() }
})

app.use(router.routes())
app.use(router.allowedMethods())

// Configure Feathers REST
app.configure(rest())

// Register Feathers services
app.use('/api/todos', todoService)

Lifecycle Methods

The listen() method starts the server and calls setup() on all services:
const server = await app.listen(3030)
console.log('Server started on port 3030')

TypeScript Support

import { feathers, Service } from '@feathersjs/feathers'
import { koa, Application } from '@feathersjs/koa'

interface User {
  id: number
  email: string
  name: string
}

interface ServiceTypes {
  users: Service<User>
}

const app: Application<ServiceTypes> = koa(feathers())

app.use('/users', {
  async find() {
    return [{ id: 1, email: 'user@example.com', name: 'User' }]
  }
})

await app.listen(3030)

Middleware Execution Order

Understanding middleware order is crucial in Koa:
import { koa, rest, bodyParser, errorHandler } from '@feathersjs/koa'

const app = koa(feathers())

// 1. Error handler (first to catch all errors)
app.use(errorHandler())

// 2. Global middleware
app.use(async (ctx, next) => {
  console.log('Request:', ctx.method, ctx.path)
  await next()
  console.log('Response:', ctx.status)
})

// 3. Body parser
app.use(bodyParser())

// 4. REST configuration (sets up service routing)
app.configure(rest())

// 5. Custom routes
app.use(async (ctx, next) => {
  if (ctx.path === '/custom') {
    ctx.body = { custom: true }
  } else {
    await next()
  }
})

// 6. Services (handled by REST transport)
app.use('/users', userService)

API Reference

koa(feathersApp?, koaApp?)

Wraps a Feathers application with Koa. Parameters:
  • feathersApp - A Feathers application instance
  • koaApp - Optional existing Koa app
Returns: Combined Feathers + Koa application

rest(options?)

Configures the REST transport. Options:
  • formatter - Custom response formatter middleware
  • authentication - Authentication settings
    • service - Authentication service name
    • strategies - Array of strategy names

errorHandler()

Koa error handling middleware that catches errors and formats them as JSON.

bodyParser(options?)

Parses request bodies. Wraps koa-body. Options: See koa-body documentation

cors(options?)

Enables CORS. Wraps @koa/cors. Options: See @koa/cors documentation