In Feathers, every service is registered at a specific path that becomes its API endpoint. The path determines how clients access the service through REST, Socket.io, or other transports.
import { feathers } from '@feathersjs/feathers'const app = feathers()// Service available at /usersapp.use('/users', userService)// Service available at /messages app.use('/messages', messageService)// Service available at /api/postsapp.use('/api/posts', postService)
The path you register becomes the base URL for all service method calls:
Feathers automatically normalizes service paths by stripping leading and trailing slashes:
Path Normalization
// All of these register the service at 'users'app.use('users', userService)app.use('/users', userService)app.use('/users/', userService)app.use('users/', userService)// All of these access the same serviceapp.service('users')app.service('/users')app.service('/users/')app.service('users/')
Leading and trailing slashes are always stripped, so /users/ and users refer to the same service.
app.use('/', rootService)// Access the root serviceconst result = await app.service('/').get('status')// REST endpoints:// GET / → find()// GET /:id → get(id)// POST / → create(data)
Mount entire Feathers applications as sub-applications to create modular, versioned APIs:
Sub-Applications
import { feathers } from '@feathersjs/feathers'// Create main appconst app = feathers()// Create a sub-application for API v1const apiV1 = feathers()apiV1.use('/users', userServiceV1)apiV1.use('/posts', postServiceV1)apiV1.use('/comments', commentServiceV1)// Create a sub-application for API v2const apiV2 = feathers()apiV2.use('/users', userServiceV2)apiV2.use('/posts', postServiceV2)// Mount sub-apps with prefixapp.use('/api/v1', apiV1)app.use('/api/v2', apiV2)// Services are now available at:// - /api/v1/users// - /api/v1/posts// - /api/v1/comments// - /api/v2/users// - /api/v2/posts
app.use('/Users', userService) // /Users (case-sensitive)app.use('/USERS', adminUserService) // /USERS (different service)app.service('users') // Not foundapp.service('Users') // Foundapp.service('USERS') // Found (different service)
To make routing case-insensitive:
Case-Insensitive Routing
const router = new Router()router.caseSensitive = falserouter.insert('/users', { service: 'users' })// All of these match the same routerouter.lookup('/users')router.lookup('/Users')router.lookup('/USERS')