Skip to content

Adapters Overview

Drizzle Cube adapters integrate seamlessly with popular web frameworks, providing framework-specific optimizations while maintaining consistent semantic layer functionality.

Choose the adapter that matches your web framework:

All adapters provide:

  • Framework Integration - Native middleware and plugin patterns
  • Request Context - Automatic user context and tenant isolation
  • Authentication - Built-in auth helpers and security middleware
  • Error Handling - Framework-specific error responses
  • TypeScript Support - Full type safety with framework types
  • Performance Optimizations - Framework-specific caching and query optimization

Drizzle Cube adapters follow a consistent pattern:

import { createCubeRouter } from 'drizzle-cube/adapters/express'
const cubeRouter = createCubeRouter({
cubes: [usersCube, ordersCube, productsCube],
drizzle: db,
schema,
// Called for EVERY request - your security boundary
extractSecurityContext: async (req, res) => ({
organisationId: req.user.orgId,
userId: req.user.id
})
});
app.use('/', cubeRouter); // defaults to /cubejs-api/v1

Each adapter exposes the same options under its own factory - createCubeRouter / createCubeApp (Express), cubePlugin / createCubeApp (Fastify), createCubeApp (Hono) and createCubeHandlers (Next.js).

All four adapters accept a pre-built semanticLayer instead of cubes. This is how an application opts into per-tenant cube sets, since it must own the SemanticLayerCompiler to call registerCubeSet:

import { SemanticLayerCompiler } from 'drizzle-cube/server'
const semanticLayer = new SemanticLayerCompiler({
drizzle: db,
schema,
contextToCubeSetId: (ctx) => String(ctx.organisationId)
});
semanticLayer.registerCube(usersCube);
semanticLayer.registerCubeSet('org-123', [customOrdersCube]);
const cubeRouter = createCubeRouter({ semanticLayer, drizzle: db, schema, extractSecurityContext });

GET /meta resolves extractSecurityContext like every other route and returns only that tenant’s cubes. Two consequences even if you change no code:

  • /meta now invokes your extractor. It previously did not. If your extractor throws for unauthenticated requests, anonymous /meta calls will fail - return SINGLE_TENANT_CONTEXT (from drizzle-cube/server) for anonymous requests if you want metadata to stay public.
  • /meta is no longer publicly cacheable. Every REST response (/meta, /load, /sql, /dry-run, /batch, /explain) now sets Cache-Control: private, no-store, so none of them may be stored in a shared cache or CDN keyed on URL alone.

Need support for a different framework? Check out our guide on building custom adapters to integrate Drizzle Cube with any web framework.

  1. Choose your framework from the adapters above
  2. Install the adapter package via npm
  3. Follow the documentation for setup instructions
  4. Check out the examples for complete implementation patterns

Each adapter includes comprehensive documentation with setup guides, configuration options, and integration examples.