This CDK project is a sample solution for friend microservices in games.
The sample solution contains AWS Lambda Functions, Amazon DynamoDB Tables, Amazon SQS Queues and Amazon API Gateway.
- the solution is constructed with only serverless services
- the solution handles friend state management asynchronously
- the solution utilizes DynamoDB Streams with Event Source Mapping Filters to reduce number of transactional writes
- the solution has an SQS queue in front, so multiple backend services can send friend actions
- the solution is decoupled from player management, it simply serves friend state management
- the solution handles duplicated messages from SQS using Event Source Mapping Filters
- another service, such as a notification service, has bidirectional connection with clients
- player metadata is stored separately with all player IDs matched
The system uses an event-driven architecture with DynamoDB Streams and event source mapping filters to handle friend state transitions asynchronously.
- A Write API (API Gateway + Lambda) accepts friend actions from the web UI and forwards them to SQS
- Game backend services can also send messages directly to the Front Queue (SQS)
- The frontHandler processes SQS messages and writes to DynamoDB
- Four State Handlers react to DynamoDB Stream events via filtered event source mappings
- A Read API (API Gateway + Lambda) serves friend list queries and isFriend checks
Mermaid source (text version)
flowchart LR
subgraph Clients
FE["🌐 Web UI"]
BE["🎮 Game Backend"]
end
subgraph Write Path
WAPI["Write API<br/>(API Gateway)"]
WH["writeHandler"]
SQS["frontQueue<br/>(SQS)"]
FH["frontHandler"]
end
subgraph Storage
DDB["Friend Table<br/>(DynamoDB)"]
STREAM["DynamoDB Stream"]
end
subgraph "State Handlers"
RQH["requestStateHandler<br/>INSERT + Requested"]
AH["acceptStateHandler<br/>MODIFY Pending→Friends"]
RJH["rejectStateHandler<br/>REMOVE Pending"]
UH["unfriendStateHandler<br/>REMOVE Friends"]
end
subgraph Read Path
RAPI["Read API<br/>(API Gateway)"]
RH["readHandler"]
end
DLQ["DLQ (SQS)"]
FE -->|"POST /friends"| WAPI
BE -->|"SendMessage"| SQS
WAPI --> WH --> SQS -->|"Event Source"| FH
FH -->|"Write"| DDB --> STREAM
STREAM -->|"Filtered"| RQH & AH & RJH & UH
RQH & AH & RJH & UH -->|"Write"| DDB
RQH & AH & RJH & UH -.->|"onFailure"| DLQ
FE -->|"GET /friends/{id}"| RAPI --> RH -->|"Query"| DDB
Each entry represents friend state from the perspective of a player with the player ID against a friend with the friend ID.
| PK: player_id | SK: friend_id | state | last_updated |
|---|---|---|---|
| string: player ID | string: friend ID | string: friend state | time stamp |
- Requested
- State that the requester sees on his/her entry after sending a friend request
- Pending
- State that the receiver sees on his/her entry after receiving a friend request
- Friends
- State that both players see on their entries once they become friends
- Request
- initial action to send a friend request to another player
- Accept
- an action to accept a pending friend request from another player
- this can only be triggered by the receiver
- Reject
- an action to reject a pending friend request from another player
- this can only be triggered by the receiver
- Unfriend
- an action to break off a completed friend relationship between two players
- this can be triggered by both players
{
"player_id": string,
"friend_id": string,
"friend_action": Friend Action,
}
- An AWS account
- Node.js 22.x or later
- Install Docker Engine or Finch (Docker alternative for macOS)
To deploy the example stack to your default AWS account/region, under project root folder, run:
pnpm installto install all the dependenciescdk deployto deploy this stack to your default AWS account/region
To run the test suite:
pnpm testNote: Tests require Docker or Finch to be running for CDK stack synthesis. If using Finch instead of Docker, the test script is already configured with CDK_DOCKER=finch.
A local single-page app is included at frontend/index.html for testing friend workflows interactively.
- Open
frontend/index.htmlin your browser - Paste the Read API and Write API URLs from the
cdk deployoutput (they persist in localStorage) - Use the From / Action / To dropdowns to send friend actions between 4 players (Alice, Bob, Charlie, Diana)
- The friend graph visualizes relationships in real-time with color-coded state edges
- Click player tabs to inspect each player's friend list and states
You can send friend actions via the Write API:
curl -X POST 'https://<WRITE API URL>/friends' \
-H 'Content-Type: application/json' \
-d '{"player_id":"player1","friend_id":"player2","friend_action":"Request"}'Or send directly to SQS (for backend-to-backend scenarios):
aws sqs send-message-batch --queue-url <QUEUE URL> \
--entries file://test/testMessages<First|Second|Third>.json
If you want to test corner cases, try this:
aws sqs send-message-batch --queue-url <QUEUE URL> \
--entries file://test/cornerCase<1|2>.json
With curl:
$ curl -X GET 'https://<YOUR ENDPOINT>/friends/player1'
This solution is licensed under the MIT-0 License. See the LICENSE file.
Also, this application uses below open source project,
