Use Case

Internal product APIs with embedded analytics

Layer type-safe analytics into the backend you already run. Keep product routes stable while exposing analytics under an internal namespace.

Contract impact

Zero endpoint breakage

Execution model

In-process + routed

Migration style

Endpoint-by-endpoint

Keep route contracts stable

Existing API consumers keep working while analytics ships behind internal paths.

Use one query definition

Call analytics from handlers with api.run(...) and expose the same logic via HTTP.

Scale rollout safely

Start with one endpoint, validate outcomes, then expand into a broader internal API surface.

Implementation flow

Step 1

Mount internal routes

Add HypeQuery under a dedicated internal namespace beside current handlers.

Step 2

Compose in endpoints

Pull analytics into product responses directly from business endpoints.

Step 3

Reuse query logic

Keep one typed source of truth for both in-process and routed analytics execution.

Works with your existing routes

Your backend stays in control. Mount HypeQuery routes where you want them.

import { createFetchHandler } from '@hypequery/serve';const hypequeryHandler = createFetchHandler(api.handler);app.route('/api/products', products);app.all('/internal/hq/*', (c) => hypequeryHandler(c.req.raw));

Compose analytics directly in business endpoints

Use api.run(...) from existing handlers whenever product responses need analytics context.

const productId = c.req.param('productId').toUpperCase();const analytics = await api.run('productOverview', {  productId,});return c.json({ productId, analytics });

Define once, reuse everywhere

The same query definitions can power internal HTTP routes and in-process calls.

const serve = initServe({  context: () => ({ db }),});export const api = serve.define({  basePath: '/internal/hq',  queries: serve.queries({    topProducts: query      .output(z.array(z.object({        product_id: z.string(),        avg_order_value: z.number(),      })))      .query(({ ctx }) =>        ctx.db          .table('analytics.orders')          .select(['payment_type as product_id'])          .count('trip_id', 'orders')          .avg('order_total', 'avg_order_value')          .groupBy(['payment_type'])          .execute()      ),  }),});

Ready to implement

Use this as your first production migration path

  • Keep existing consumer contracts intact
  • Move analytics logic into typed definitions
  • Expand exposure only when your team is ready