Pikku 0.8 — Our Biggest Release Yet!
After months of focused work, I'm thrilled to introduce Pikku 0.8 — the biggest update yet to the typed backend framework I’ve been building to simplify full-stack infrastructure.
This release marks a turning point: Pikku is no longer just for HTTP / Websockets and CronJobs — it’s now a complete platform for building scalable, typed, multi-transport backends. Whether you're targeting HTTP, queues, RPCs, or even AI agents — you now write your logic once, then connect it anywhere.
🧠 Quick Recap: What is Pikku?
At its core, Pikku is a developer-first framework for declaring backend logic as typed functions, then wiring those functions up to various transports — like HTTP, WebSocket, RPC, queues, or AI agent servers.
If you're familiar with function-based backends or serverless APIs, you’ll feel right at home — but Pikku brings full typings, permissions, and tooling to the party.
Here’s what a typical Pikku function looks like:
const updateTodo = pikkuFunc<Todo, { updated: boolean }>({
func: async ({ logger, todoService }, { todoId, ...data }, session) => {
await todoService.update(todoId, data)
return { updated: true }
},
permissions: {
canEditTodo: async ({ todoService }, data, session) => {
const { ownerId } = await todoService.get(data.todoId)
return ownerId === session.userId
}
}
})
Then you wire it up to the desired transport:
addHTTPRoute({
method: 'patch',
func: updateTodo,
})
📚 Learn more → Function Basics 📚 Learn more → HTTP APIs & Routing
⚡ New in 0.8: Remote Procedure Calls (RPCs)
You can now invoke Pikku functions via RPC — from clients, other services, or across your infrastructure.
If you're unfamiliar with RPCs, here's a primer: 🧠 What is RPC? → Martin Fowler
Server-side usage:
await rpc.invoke('send-Email', { type: 'todo-changed', todoId })
Typed client usage:
const rpc = new PikkuRPC()
const result = await rpc.invoke('update-todo', { type, todoId })
RPCs in Pikku:
- Are typed with schema validation
- Respect permissions and sessions
- Work identically whether local or remote
- Are tree-shakeable for minimal bundles
🧵 Queue Workers
Pikku now supports async job queues with the same function-first philosophy.
Think of it like typed background workers — perfect for sending emails, processing images, or handling long-running tasks.
const queueWorker = pikkuSessionlessFunc<
{ message: string; fail: boolean },
{ result: string }
>(async ({}, data) => {
if (data.fail) throw new Error('Job failed intentionally')
return { result: `echo: ${data.message}` }
})
addQueueWorker({
queueName: 'hello-world-queue',
func: queueWorker,
})
Run your preferred queue system (e.g., BullMQ or pg-boss):
const bullQueueWorkers = new BullQueueWorkers(
{},
singletonServices,
createSessionServices
)
await bullQueueWorkers.registerQueues()
Client usage:
// The QueueService is literally just a typed wrapper
const queueService = new PikkuQueue(new BullQueueService())
await queueService.add('hello-world-queue', { message: 'Hello', fail: false })
🤖 MCP Server: Build Agent-Compatible Backends
The MCP Server allows your Pikku functions to be used by AI agents — as tools, resources, or prompt generators. You can build your own local agent server, integrate with LLMs, or support emerging agent standards.
If you're new to agents or tool-calling: 🧠 What are AI agents? → LangChain Blog 🧠 Tool-Use in LLMs → OpenAI
Tools
Declare a function as a callable “tool”:
const sayHello = pikkuMCPToolFunc<{ name?: string }>(
async ({ logger }, { name = 'World' }) => {
logger.info(`Hello ${name}`)
return [{ type: 'text', text: `Hello, ${name}!` }]
}
)
addMCPTool({
name: 'sayHello',
description: 'Greet someone with a friendly message',
func: sayHello,
})
Resources
Expose structured data as accessible agent resources:
const getUserInfo = pikkuMCPResourceFunc<{ userId: string }>(
async ({ users }, { userId }) => {
const user = users[userId]
if (!user) throw new NotFoundError(`User not found`)
return [{ uri: `getUserInfo/${userId}`, text: JSON.stringify(user) }]
}
)
Prompts
Dynamically generate prompts for LLMs:
const dynamicPromptGenerator = pikkuMCPPromptFunc<{
topic: string
complexity: 'beginner' | 'intermediate' | 'advanced'
includeExamples?: boolean
}>(async ({ logger }, { topic, complexity, includeExamples }) => {
let content = `# Learning ${topic} (${complexity})\n\n`
content += complexity === 'beginner'
? `Start with the basics.\n`
: complexity === 'intermediate'
? `Go deeper.\n`
: `Covering edge cases.\n`
if (includeExamples) content += `\n## Examples\n- Example 1\n- Example 2\n`
return [{ role: 'user', content: { type: 'text', text: content } }]
})
Running the MCP Server
const server = new PikkuMCPServer({
name: 'pikku-mcp-server',
version: '1.0.0',
mcpJsonPath: join(__dirname, '../../functions/.pikku/mcp.gen.json'),
capabilities: { logging: {}, tools: {}, resources: {}, prompts: {} },
}, singletonServices)
await server.init()
await server.connect(new StdioServerTransport())
server.wrapLogger()
🎯 Service Shaking: Smarter, Smaller Builds
Think tree-shaking, but for backend services.
You can now exclude unused services from your production bundle using tag-based CLI filters:
pikku --tags 'web,queue'
This tells Pikku to only include services used by functions tagged with web
or queue
.
Benefits:
- Smaller bundles
- Lazy-loaded service dependencies
- More precise deployments
if (singletonServices.jwt) {
const { JoseJWTService } = await import('@pikku/jose')
jwt = new JoseJWTService(...)
}
📚 Learn more → Service Shaking
🚧 Coming Next
We consider Pikku 0.8 feature complete, in the sense we won't be adding more transports or core library changes.
In the near future, we’ll focus on:
- 🐛 Fixing minor bugs
- 🧑🏽💻 Adding APIs to exising wrappers like Queues or oAuth/Notifications to MCP
- 🧾 Improving docs and examples
- 💬 Expanding tutorials and templates
- ✨ Polish across CLI and DX
If you're building something and get stuck — please open an issue or ask us on GitHub Discussions.
🔍 Peek: AI-Assisted Lookup One of the things I love about Pikku is that everything is statically documented — from services to queues to functions.
I’m exploring the idea of a Pikku-powered MCP agent — a local AI assistant that gives instant answers like:
“What queues are available in this service?” “Which function handles updating a todo?”
No need to crawl the codebase or guess — just ask. If this sounds interesting, stay tuned.
🙌 Final Thoughts
Pikku 0.8 isn’t just a version bump — it’s a foundational leap forward.
By treating functions as your backend contract, you gain:
- ✅ Full TypeScript safety
- 🔐 Auth & permission guards
- 🔁 Transport-agnostic logic
- 🧵 Queue & background job support
- 🧠 Agent / AI integration
- 🧼 Tree-shaken builds for tighter deployments
Whether you're building real-time apps, internal tools, microservices, or intelligent agents — Pikku 0.8 gives you a fast, typed, and scalable foundation.
🚀 Try It Now
Thanks for reading — I can't wait to see what you build.
— Yasser