Living Systems Handbook microservices as humans Bipin Singh
Anatomy of one human

Memory

2 min readChapter 07 of 34By Bipin Singh

A person's memories are their own. You can ask a friend what they remember, but you can't reach into their head and rewrite it. Microservices follow the same rule: each service owns its data, and others get it only by asking or listening.

Kinds of memory

Human memory Service storage AWS
Long-term memory The service's database — orders, customers, state DynamoDB, Aurora
Photo albums and documents Files and large objects S3
Short-term memory Cache for fast repeated recall ElastiCache, DynamoDB DAX, in-function caching
Muscle memory / habits Configuration SSM Parameter Store, AppConfig
Secrets kept close Credentials and keys Secrets Manager
Forgetting Data expiry and retention DynamoDB TTL, S3 lifecycle rules

Never share a brain's memory

The most damaging microservice mistake is many services reading and writing the same database tables. It's like several people sharing one notebook with no rules: someone changes a page's format and everyone else breaks.

Shared database Owned memory
Any schema change can break other services Each service changes its own schema freely
Services are coupled through data Services are coupled only through APIs and events
Unclear who's responsible for data quality One clear owner

If another service needs your data, it should:

  1. Ask you through your API ("what's the status of order 42?"), or
  2. Listen to your events and keep its own copy of the parts it needs ("I'll note every OrderPlaced in my kitchen queue").

DynamoDB: a natural memory for serverless humans

DynamoDB is a serverless key-value database: no servers, scales automatically, pay per request (on-demand), single-digit-millisecond reads. Design starts from the questions the service will ask its memory:

Question the Waiter asks Key design
"Get order 42" pk = ORDER#42, sk = ORDER#42
"List open orders for table 4" Global secondary index: gsi1pk = TABLE#4, gsi1sk = STATUS#PLACED#<time>
// memory/order-memory.ts — the adapter that implements the brain's OrderMemory port
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand, GetCommand } from "@aws-sdk/lib-dynamodb";
import type { Order, OrderMemory } from "../brain/place-order";

const db = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const TABLE = process.env.TABLE_NAME!;

export const orderMemory: OrderMemory & { recall(id: string): Promise<Order | undefined> } = {
  async save(order) {
    await db.send(new PutCommand({
      TableName: TABLE,
      Item: {
        pk: `ORDER#${order.orderId}`,
        sk: `ORDER#${order.orderId}`,
        gsi1pk: `TABLE#${order.tableNumber}`,
        gsi1sk: `STATUS#${order.status}#${order.placedAt}`,
        ...order,
      },
      ConditionExpression: "attribute_not_exists(pk)", // never overwrite an existing order
    }));
  },
  async recall(orderId) {
    const res = await db.send(new GetCommand({ TableName: TABLE, Key: { pk: `ORDER#${orderId}`, sk: `ORDER#${orderId}` } }));
    return res.Item as Order | undefined;
  },
};

Forgetting is healthy

People forget unimportant things; services should too. Storing everything forever costs money and can breach privacy rules.

Short-term memory: caching

If the Waiter checks the menu prices for every order, cache them for a few minutes — prices rarely change. Options range from a simple variable outside the Lambda handler (reused while that copy stays warm) to ElastiCache for shared caches.

Watch out

A cache can lie: it may hold stale data. Always decide how stale is acceptable (the TTL) for each cached item.

Memory that survives disasters

Key idea

One human, one memory. Share knowledge by talking and announcing — never by letting others reach into your database.

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