railiz-serverless
v0.2.8
Published
Serverless adapter and modular architecture layer for Railiz, enabling lightweight, scalable Node.js backends.
Maintainers
Readme
🌐 railiz-serverless
🚀 Serverless adapter & modular architecture layer for railiz.
railiz-serverless extends railiz for serverless environments and scalable architecture.
Why railiz-serverless?
Building serverless backends usually means:
- Boilerplate for Lambda adapters
- Difficulty structuring large codebases
- Context mismatch between platforms
railiz-serverless solves these while staying minimal and fast.
Features
- ☁️ AWS Lambda adapter (zero boilerplate)
- 🧩 Module-based architecture (
app.plugin) - 🧠 Deterministic execution (powered by railiz)
- 🪶 Ultra-lightweight plugin-first architecture.
- 📝 Full TypeScript inference
- 🌐 Works anywhere railiz runs
Mental Model
Lambda Event
↓
Adapter (normalize request)
↓
Railiz Context (ctx)
↓
Middleware Pipeline
↓
Router
↓
Handler
↓
Lambda ResponseInstallation
npm install railiz railiz-serverlessRequires Node.js 18+
Usage
Quick Example
import { createServerlessApp } from 'railiz-serverless'
const { app, handler } = createServerlessApp()
app.get('/hello', (ctx) => {
return ctx.ok({ message: 'Hello Lambda' })
})
export { handler }There are two ways to use railiz-serverless.
| Approach | Description | |--------|-------------| | App Factory | Recommended. Fast, clean setup | | Manual Setup | Full control, more flexible |
1️⃣ App Factory
Use for clean, declarative setup.
// users.module.ts
import { Railiz } from 'railiz'
export function usersModule(app: Railiz) {
app.group('/users', (r) => {
r.get('/', (ctx) => ctx.ok([]))
r.get('/:id', (ctx) => ctx.ok({ id: ctx.params.id }))
})
}// posts.module.ts
import { Railiz } from 'railiz'
export function postsModule(app: Railiz) {
app.group('/posts', (r) => {
r.get('/', ctx => ctx.ok([]))
})
}// handler.ts
import { createServerlessApp } from 'railiz-serverless'
import { usersModule } from './users.module'
import { postsModule } from './posts.module'
const { app, handler } = createServerlessApp({
plugins: [usersModule, postsModule],
debug: true,
})
export { handler }2️⃣ Manual Setup (Advanced)
Use when you need fine-grained control.
app.ts
// app.ts
import { bodyParser, queryParser, Railiz } from 'railiz'
import { usersModule } from './users.module'
import { postsModule } from './posts.module'
const app = new Railiz()
// example
app.use(queryParser())
app.use(bodyParser())
// plugin
app.plugin(usersModule)
app.plugin(postsModule)
// exmaple
app.get('/hello', (ctx) => {
return ctx.ok({ message: 'Hello from Lambda 🚀' })
})
export default apphandler.ts
// handler.ts
import app from './app'
import { lambdaAdapter } from 'railiz-serverless'
export const handler = lambdaAdapter(app, {
debug: true,
})Both approaches support modules — only the wiring differs.
Context API
railiz-serverless uses the same context system as railiz.
All features such as:
- routing
- middleware
- plugins
- request parsing
- response helpers
work exactly the same as in railiz.
Local Development
- You can run the Lambda handler locally without deploying to AWS.
- This helps with debugging, testing routes, and simulating API Gateway events.
This is useful for:
- testing handlers
- debugging requests
- simulating API Gateway events
Create a local test file
lambda-test.ts
import { createServerlessApp } from './index'
const { app, handler } = createServerlessApp({
debug: true,
})
app.get('/hello', (ctx) => {
return ctx.ok({ message: 'Hello world from Lambda!' })
})
// Simulate a Lambda event locally
const event = {
version: '2.0',
routeKey: '$default',
rawPath: '/hello',
rawQueryString: '',
headers: { host: 'localhost' },
requestContext: {
http: { method: 'GET', path: '/hello' },
requestId: 'test',
},
isBase64Encoded: false,
body: null,
cookies: [],
}
async function run() {
const result = await handler(event as any)
console.log(JSON.stringify(result, null, 2))
}
run()Run the test
npx tsx lambda-test.tsExample output
{
"statusCode": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"message\":\"Hello from Lambda 🚀\"}",
"isBase64Encoded": false
}Test POST requests
You can simulate a POST request by adding a body.
const event = {
version: '2.0',
rawPath: '/users',
rawQueryString: '',
headers: {
'content-type': 'application/json'
},
requestContext: {
http: {
method: 'POST',
path: '/users'
},
requestId: 'local-test-id'
},
body: JSON.stringify({
name: 'John'
}),
isBase64Encoded: false
}Dev scripts
npx tsx lambda-test.tsArchitecture
AWS Lambda
↓
railiz-serverless (adapter)
↓
Railiz Core
↓
Router → Middleware → HandlersComparison
How railiz-serverless compares with other popular approaches.
| Criteria | railiz-serverless | Raw Lambda | Express on Lambda | Hono | NestJS / Lambda | | -------------- | ----------------- | ---------- | ----------------- | --------------| --------------- | | Boilerplate | 🪶 minimal | ❌ high | ⚠️ medium | 🪶 minimal | ⚠️ medium-high | | Structure | 🧩 modular | ❌ none | ⚠️ manual | ⚠️ lightweight | ✅ full | | Performance | ⚡ high | ⚡ high | ⚠️ overhead | ⚡ very high | ⚠️ overhead | | Cold Start | ⚡ very fast | ⚡ fast | ⚠️ slower | ⚡ very fast | ❌ slow | | Bundle Size | 🪶 very small | 🪶 small | ⚠️ medium | 🪶 very small | ❌ large | | Type Safety | ✅ strong | ❌ none | ❌ weak | ✅ strong | ✅ strong | | Scalability | ✅ high | ❌ low | ⚠️ medium | ✅ high | ✅ high | | Flexibility | ⚡ very high | ⚡ very high. | ⚠️ medium | ⚡ high | ⚠️ opinionated | | Learning Curve | ✅ low | ✅ low | ⚠️ medium | ✅ low | ❌ high | | Built-in | ❌ minimal | ❌ none | ❌ minimal | ❌ minimal | ✅ rich |
Summary:
- railiz-serverless → best for performance & simplicity
- Raw Lambda → lowest level control but no structure
- Express on Lambda → familiar but not optimized
- NestJS / Lambda → powerful but heavier and slower
👉 railiz-serverless hits the sweet spot between performance and structure.
Why Railiz fits Serverless
Serverless requires:
- fast cold starts
- minimal runtime overhead
- stateless execution
- predictable performance
👉 railiz is designed exactly for that
Minimal Core
Unlike heavy frameworks, railiz has:
- no dependency injection container
- no decorators at runtime
- no reflection or metadata scanning
👉 Result: smaller bundle + faster startup
Deterministic Execution
middleware → router → handler- no hidden lifecycle
- no magic hooks
Zero Overhead
- no extra abstraction layers
- no runtime cost beyond your logic
👉 only your logic runs
Stateless by Design
Railiz encourages stateless architecture:
- in-memory sessions
- global mutable state
- long-lived connections
Plugin-first
Everything is opt-in:
app.use(json())
app.use(queryParser())
app.use(cors())👉 only load what you need
When NOT to use railiz-serverless
- If you need full DI framework → use NestJS
- If you need built-in ORM / auth → use fullstack framework
Supported Event Sources
railiz-serverless supports:
- AWS API Gateway (HTTP API v2)
- AWS Lambda Function URL
- Application Load Balancer (ALB)
Philosophy
You control:
- architecture
- modules
- domain logic
railiz-serverless controls:
- request normalization
- runtime adaptationLicense
MIT
