Skip to content

aws-samples/friend-microservices

Friend Microservices Sample

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.

Key features

  • 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

Assumptions

  • another service, such as a notification service, has bidirectional connection with clients
  • player metadata is stored separately with all player IDs matched

Architecture

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

Architecture Diagram

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
Loading

DynamoDB Tables

Friend Table

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

Friend States

  • 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

Friend Actions

  • 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

Friend Action Message

{
    "player_id": string,
    "friend_id": string,
    "friend_action": Friend Action,
}

Prerequisites

  • An AWS account
  • Node.js 22.x or later
  • Install Docker Engine or Finch (Docker alternative for macOS)

Usage

Deployment

To deploy the example stack to your default AWS account/region, under project root folder, run:

  1. pnpm install to install all the dependencies
  2. cdk deploy to deploy this stack to your default AWS account/region

Test

Running Tests

To run the test suite:

pnpm test

Note: 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.

Web UI

A local single-page app is included at frontend/index.html for testing friend workflows interactively.

  1. Open frontend/index.html in your browser
  2. Paste the Read API and Write API URLs from the cdk deploy output (they persist in localStorage)
  3. Use the From / Action / To dropdowns to send friend actions between 4 players (Alice, Bob, Charlie, Diana)
  4. The friend graph visualizes relationships in real-time with color-coded state edges
  5. Click player tabs to inspect each player's friend list and states

Send Test Friend Action Events

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

Get Test Friend Data

With curl:

$ curl -X GET 'https://<YOUR ENDPOINT>/friends/player1'

License

This solution is licensed under the MIT-0 License. See the LICENSE file.

Also, this application uses below open source project,

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors