Skip to content

ADR-006: Hono Framework for Edge API ​

Status: Accepted
Date: 2026-02-01
Deciders: Abdisamed Mohamed
Related ADRs: ADR-002 (Edge-First Architecture)

Context ​

CepatEdge requires a lightweight, fast API framework optimized for Cloudflare Workers. The framework must support:

  • TypeScript first-class
  • Middleware system
  • Routing with parameters
  • Request/response handling
  • Error handling
  • Performance optimization
  • Small bundle size
  • Edge runtime compatibility

Traditional Node.js frameworks (Express, Fastify, Koa) are too heavy for edge environments and include unnecessary features.

Decision ​

Use Hono framework for the CepatEdge API layer.

Implementation ​

Core Architecture ​

typescript
import { Hono } from 'hono';

// Type-safe Hono app with environment
type Env = {
  CEPATEDGE_CACHE: DurableObjectNamespace;
  DATABASE_URL: string;
  JWT_SECRET: string;
};

const app = new Hono<{ Bindings: Env }>();

// Middleware
app.use('*', cors());
app.use('/api/*', authMiddleware);

// Routes
app.get('/api/health', (c) => c.json({ status: 'ok' }));

app.get('/api/maintenance', async (c) => {
  const user = c.get('user');
  const params = c.req.query();

  // Business logic here
  return c.json({ data: [] });
});

// Error handling
app.onError((err, c) => {
  console.error(err);
  return c.json({ error: 'Internal server error' }, 500);
});

export default app;

Middleware System ​

typescript
// Authentication middleware
const authMiddleware: MiddlewareHandler = async (c, next) => {
  const token = c.req.header('Authorization')?.replace('Bearer ', '');

  if (!token) {
    return c.json({ error: 'Unauthorized' }, 401);
  }

  const user = await authenticateUser(token, c.env);
  c.set('user', user);

  await next();
};

// Role-based authorization
const roleMiddleware = (roles: string[]): MiddlewareHandler => {
  return async (c, next) => {
    const user = c.get('user');

    if (!user || !roles.includes(user.role)) {
      return c.json({ error: 'Forbidden' }, 403);
    }

    await next();
  };
};

// Usage in routes
app.get('/api/admin/users', roleMiddleware(['admin']), async (c) => {
  // Admin-only logic
});

Performance Optimizations ​

typescript
// Response caching
app.get('/api/public/data', cacheMiddleware(300), async (c) => {
  // Cached for 5 minutes
});

// Streaming responses
app.get('/api/reports/export', async (c) => {
  const stream = generateReportStream();
  return new Response(stream, {
    headers: { 'Content-Type': 'application/octet-stream' }
  });
});

Consequences ​

Positive ​

  • Edge Optimized: Built specifically for Cloudflare Workers
  • TypeScript First: Comprehensive type safety
  • Lightweight: Minimal bundle size (<50KB)
  • Fast: Optimized for edge performance
  • Middleware System: Flexible request processing
  • Developer Experience: Intuitive API, excellent documentation

Negative ​

  • Learning Curve: New framework for team members
  • Ecosystem: Smaller community than Express/Fastify
  • Edge-Specific: Not suitable for traditional server environments
  • Limited Features: Focused scope, fewer built-in features

Mitigation ​

  • Documentation: Comprehensive guides and examples
  • Migration Path: Clear migration strategy from existing APIs
  • Testing: Built-in testing utilities and patterns
  • Community: Growing ecosystem with good support

Performance Benchmarks ​

Bundle Size ​

  • Core Framework: ~15KB gzipped
  • With Middleware: ~25KB gzipped
  • Full Application: ~45KB gzipped

Response Times ​

  • Simple Routes: <5ms
  • Database Routes: <50ms (with caching)
  • Complex Logic: <100ms
  • Error Handling: <10ms

Memory Usage ​

  • Base Application: <10MB
  • With Caching: <25MB
  • Peak Load: <50MB

Alternatives Considered ​

Express.js ​

  • Pros: Mature, large ecosystem, familiar API
  • Cons: Heavy bundle size, not edge-optimized, Node.js specific

Fastify ​

  • Pros: High performance, plugin ecosystem, validation
  • Cons: Bundle size, learning curve, not edge-native

Workers Native API ​

  • Pros: Direct Workers API, maximum performance
  • Cons: Verbose, error-prone, no structure

SvelteKit API Routes ​

  • Pros: Framework integration, file-based routing
  • Cons: Additional complexity, not edge-focused

Developer Experience ​

Type Safety ​

typescript
// Full type inference
app.get('/api/users/:id', async (c) => {
  const id = c.req.param('id'); // Typed as string
  const user = await getUser(id); // Return type inferred
  return c.json(user); // Response type checked
});

Middleware Composition ​

typescript
// Composable middleware
const apiMiddleware = compose([
  cors(),
  rateLimit(),
  auth(),
  logging()
]);

app.use('/api/*', apiMiddleware);

Error Handling ​

typescript
// Centralized error handling
app.onError((err, c) => {
  // Log error with context
  console.error({
    error: err.message,
    path: c.req.path,
    user: c.get('user')?.id,
    timestamp: Date.now()
  });

  // Return appropriate error response
  if (err instanceof ValidationError) {
    return c.json({ error: 'Validation failed' }, 400);
  }

  return c.json({ error: 'Internal server error' }, 500);
});

Testing Support ​

Built-in Testing Utilities ​

typescript
import { testClient } from 'hono/testing';

describe('API Routes', () => {
  const client = testClient(app);

  it('should return health status', async () => {
    const res = await client.api.health.$get();
    expect(res.status).toBe(200);
  });
});

References ​

  • Hono Framework Documentation
  • Cloudflare Workers Runtime APIs
  • CepatEdge Performance Benchmarks
  • Edge Computing Best Practices