Skip to main content

Write Backend Logic Once. Run It Everywhere.

Write your backend logic once. Pikku automatically adapts it to work with any protocol—HTTP APIs, WebSockets, queues, scheduled tasks, and even AI tools via MCP. No duplicate code, no vendor lock-in.

  • Unified backend logic across all protocols
  • Serverless or server — deploy to any platform without code changes
  • Full TypeScript type safety end-to-end
  • Production-ready with sessions, auth, and middleware

⚡ 5-minute setup • MIT Licensed

Built with Pikku

Already powering production systems across startups and platforms.

From open-source frameworks to live platforms, Pikku adapts to diverse real-world projects.

AgreeWeAgreeWeHeyGermanyHeyGermanymartamartaBambooRoseBambooRoseCalligraphy CutCalligraphy Cut

One Function. Every Protocol. Zero Duplication.

Write your logic once. Wire it to HTTP, WebSockets, queues, scheduled tasks, CLI, or AI tools (via Model Context Protocol). Same logic. Different protocols.

1. Define Your Function

src/functions/cards.function.ts
export const getCard = pikkuFunc<
{ cardId: string },
{ id: string; title: string; status: string }
>({
func: async ({ database, channel }, { cardId }) => {
const card = await database.query('cards', {
where: { id: cardId }
})

// Works with WebSocket channels and SSE too!
if (channel) {
await channel.send({ type: 'card-fetched', card })
}

return card
},
permissions: { owner: requireOwner },
docs: {
summary: 'Fetch a card by ID',
tags: ['cards']
}
})

2. Wire to Any Protocol

HTTP API
WebSocket
Server-Sent Events
Queue Worker
Scheduled Task
RPC Call
MCP (AI Tools)
CLI
HTTP API
wireHTTP({
method: 'get',
route: '/cards/:cardId',
func: getCard
})

✓ Same authentication, permissions, and validation across all protocols

Long-Running Workflows with Built-in Resilience

Coming in 0.11

Build complex, multi-step processes that survive failures, handle time delays, and maintain state across server restarts.

User Onboarding Workflow
export const onboardingWorkflow = pikkuWorkflowFunc(
async ({ workflow }, { email, userId }) => {
// Step 1: Create user profile (RPC step)
const user = await workflow.do(
'Create user profile',
'createUserProfile',
{ email, userId }
)

// Step 2: Add to CRM (inline step)
const crmUser = await workflow.do(
'Create user in CRM',
async () => crmApi.createUser(user)
)

// Step 3: Wait 5 minutes
await workflow.sleep(
'Wait before welcome email',
'5min'
)

// Step 4: Send welcome email (RPC step)
await workflow.do(
'Send welcome email',
'sendEmail',
{ to: email, template: 'welcome' }
)

return { success: true }
}
)

1. Deterministic Replay

Completed steps are cached and never re-executed. Workflows resume from where they left off after failures or delays.

2. Persistent State

Store state in any database—PostgreSQL and Redis support out of the box. Survives server restarts and you don't pay for the time it isn't running.

3. Time-Based Steps

Sleep steps for delays, reminders, trial expirations, and scheduled follow-ups.

4. RPC & Inline Steps

Mix RPC calls (via queue workers) with inline code. Full type safety across all steps.

Perfect for user onboarding, order fulfillment, payment processing, approval workflows, and any multi-step business process.

What Developers Say

Real feedback from teams using Pikku in production

"So many places in my code base have like three entry points: CLI, public (sometimes protected) HTTP API and internally from within the API. Would be so nice having everything just an invoke away. With Nest it's a pain because you basically have to start the whole API up just to run CLI command."

Alex Harley

Co-founder @ Superbridge

"Ever been annoyed at having to write your code different in a Lambda than in an express handler? Pikku fixes that."

Christoph Sitter

CTO @ spot

Ship Faster, Maintain Less

Write your business logic once and deliver features across all protocols instantly. One source of truth means fewer bugs, faster iterations, and the flexibility to pivot without rewrites.

Tiny runtime with minimal overhead. Bundles as small as 50KB for single-function deployments.

🔗
Type-Safe Clients
Auto-generated from your function definitions
HTTP fetch, WebSocket, and RPC clients with full IntelliSense
🔐
Auth & Permissions
Built-in filters, no manual checks
Cookie, bearer, API key auth with fine-grained permissions
⚙️
Services
Singleton and per-request injection
Database, logger, config—all type-safe and testable
🪆
Middleware
Before/after hooks across all protocols
Logging, metrics, tracing—work everywhere
Schema Validation
Auto-validate against TypeScript input schemas
Runtime validation catches errors before they hit your functions
🪶
Zero Lock-In
Standard TypeScript, no magic
Tiny runtime, bring your own database/logger/tools

Bundle Only What You Deploy

Run your codebase as a monolith, as microservices, or as functions. Pikku creates the smallest bundle for your use case.

🏢

Monolith

Run everything in one process

pikku
~2.8MB
All functions, all protocols
📦

Microservices

Split by domain or feature

pikku --http-routes=/admin
pikku --tags=admin
~180KB
Only admin routes + dependencies
λ

Functions

One function per deployment

pikku --http-routes=/users/:id --types=http
~50KB
Single endpoint + minimal runtime

Get Started in Minutes

Create your first Pikku app with one command. You'll have a function running across HTTP, WebSockets, and more in under 5 minutes.

npm create pikku@latest

Why I Built Pikku

Three core principles that drove Pikku's creation

💰

Cost Optimization

Start optimizing your infrastructure budget by having full freedom to switch deployments at any time

Learn about avoiding costly rewrites →

Speed & Type Safety

Build fast without any runtime lock-in, with TypeScript having your back

See how TypeScript powers everything →
🤖

AI-Era Quality

Simplicity means dramatically better generated code quality

Explore architecture flexibility →

Watch the Talks

— Yasser Fadl, Creator of Pikku

Ready to Simplify Your Backend?

Stop duplicating logic. Write once, deploy anywhere with Pikku.