Living Systems Handbook microservices as humans Bipin Singh
Pilot: Café Sukoon

Hiring the Waiter

2 min readChapter 28 of 34By Bipin Singh

We grew a Waiter in Growing one human. Now we'll give the café a proper shared world and make the Waiter's lifestyle configurable, so the same DNA can live a chilled, peaceful or rat-race life.

Lifestyle profiles

// infra/lifestyle.ts — one place that describes each way of living
import { Duration } from "aws-cdk-lib";

export type Lifestyle = "chilling" | "peace" | "ratRace";

export const PROFILES = {
  chilling: { memorySize: 256,  provisionedConcurrency: 0,  workerConcurrency: 2,  logDays: 7 },
  peace:    { memorySize: 512,  provisionedConcurrency: 0,  workerConcurrency: 10, logDays: 30 },
  ratRace:  { memorySize: 1024, provisionedConcurrency: 50, workerConcurrency: 50, logDays: 30 },
} as const;

export const TIMEOUT = Duration.seconds(10);

The shared world

// infra/cafe-stack.ts
import { Stack, StackProps, CfnOutput } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as events from "aws-cdk-lib/aws-events";
import * as apigw from "aws-cdk-lib/aws-apigatewayv2";
import { Lifestyle } from "./lifestyle";
import { Waiter } from "../services/waiter/infra/waiter";

export interface CafeStackProps extends StackProps { lifestyle: Lifestyle; }

export class CafeStack extends Stack {
  constructor(scope: Construct, id: string, props: CafeStackProps) {
    super(scope, id, props);

    const townSquare = new events.EventBus(this, "TownSquare");
    const frontDoor = new apigw.HttpApi(this, "FrontDoor", {
      corsPreflight: { allowOrigins: ["*"], allowMethods: [apigw.CorsHttpMethod.ANY], allowHeaders: ["content-type"] },
    });

    const waiter = new Waiter(this, "Waiter", { eventBus: townSquare, api: frontDoor, lifestyle: props.lifestyle });

    new CfnOutput(this, "FrontDoorUrl", { value: frontDoor.apiEndpoint });
    new CfnOutput(this, "Lifestyle", { value: props.lifestyle });
  }
}
// bin/cafe.ts — choose the lifestyle at deploy time: cdk deploy -c lifestyle=ratRace
import { App } from "aws-cdk-lib";
import { CafeStack } from "../infra/cafe-stack";
import type { Lifestyle } from "../infra/lifestyle";

const app = new App();
const lifestyle = (app.node.tryGetContext("lifestyle") ?? "peace") as Lifestyle;

new CafeStack(app, "CafeSukoon", {
  lifestyle,
  env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
});

The Waiter, lifestyle-aware

Changes to the Waiter construct from Growing one human:

import * as logs from "aws-cdk-lib/aws-logs";
import { Lifestyle, PROFILES, TIMEOUT } from "../../../infra/lifestyle";

export interface WaiterProps {
  eventBus: events.IEventBus;
  api: apigw.HttpApi;
  lifestyle: Lifestyle;
}

// …inside the constructor:
const profile = PROFILES[props.lifestyle];

const placeOrder = new nodejs.NodejsFunction(this, "PlaceOrder", {
  runtime: lambda.Runtime.NODEJS_22_X,
  architecture: lambda.Architecture.ARM_64,
  memorySize: profile.memorySize,
  timeout: TIMEOUT,
  tracing: lambda.Tracing.ACTIVE,
  entry: path.join(__dirname, "../src/senses/place-order.http.ts"),
  environment: { TABLE_NAME: this.memory.tableName, EVENT_BUS_NAME: props.eventBus.eventBusName },
  logGroup: new logs.LogGroup(this, "PlaceOrderDiary", { retention: profile.logDays as logs.RetentionDays }),
});

// In the rat race, keep warm copies and send traffic to them
const target = profile.provisionedConcurrency > 0
  ? placeOrder.addAlias("live", { provisionedConcurrentExecutions: profile.provisionedConcurrency })
  : placeOrder;

props.api.addRoutes({
  path: "/orders",
  methods: [apigw.HttpMethod.POST],
  integration: new HttpLambdaIntegration("PlaceOrderIntegration", target),
});

(logs.RetentionDays values are numbers of days such as 7 and 30, so the profile maps directly.)

Deploy

cdk deploy -c lifestyle=peace

Place an order with curl (see Growing one human) and confirm the OrderPlaced announcement in the EventBridge console (or with a temporary rule that logs all events to CloudWatch Logs — handy while learning).

Key idea

The lifestyle is now part of the DNA — visible in code review, switchable at deploy time, and identical across environments.

Bipin Singh
Written by Bipin Singh

Senior Full-Stack Engineer · AI & AWS. I design and build serverless systems on AWS — and love explaining them simply.

Work with me