Zuplo logo
Back to all articles
January 29, 2023
9 min read

Smart Routing for Microservices (or isolated customer backends)

Josh Twist
Josh TwistCo-founder & CEO

We just published a new video showing how you can add smart routing, behind a single common API for multiple backends, in 1 page of TypeScript. Metadata is loaded from an external service (in this case, Xata but you could use Supabase, Mongo etc).

Here's the code used in the demonstration:

import {
  ZuploContext,
  ZuploRequest,
  environment,
  ZoneCache,
} from "@zuplo/runtime";

interface RouteInfo {
  customerId: string;
  primaryUrl: string;
  secondaryUrl?: string;
}

const CACHE_KEY = "ROUTE_RECORDS";
const CACHE_NAME = "ROUTE_INFO";

async function loadRouteInfoFromApi(context: ZuploContext) {
  const cache = new ZoneCache(CACHE_NAME, context);

  const records = await cache.get(CACHE_KEY);

  if (!records) {
    const options = {
      method: "POST",
      headers: {
        Authorization: `Bearer ${environment.XATA_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: '{"page":{"size":15}}',
    };

    const response = await fetch(
      "https://YOUR-XATA-URL.xata.sh/db/test:main/tables/routing/query",
      options,
    );

    const data = await response.json();
    cache.put(CACHE_KEY, data.records, 300); // 5 minutes

    context.log.info("RouteInfo loaded from API");
    return data.records;
  }

  context.log.info("RouteInfo loaded from Cache");
  return records;
}

export default async function (request: ZuploRequest, context: ZuploContext) {
  const customerId = request.user.data.customerId;

  const routing = await loadRouteInfoFromApi(context);

  const routeInfo = routing.find((r) => r.customerId === customerId);

  if (!routeInfo) {
    return new Response(`No route found for customer '${customerId}'`, {
      status: 404,
    });
  }

  const response = await fetch(routeInfo.primaryUrl);
  if (response.status !== 200 && routeInfo.secondaryUrl) {
    context.log.info(
      `First request failed, trying secondary (${response.status})`,
    );
    const response2 = await fetch(routeInfo.secondaryUrl);
    return response2;
  }

  return response;
}

Got questions or feedback? Join us on Discord.

Questions? Let's chat

Join our community to discuss API integration and get help from our team and other developers.

OPEN DISCORD
51members online