Last Updated: 3/9/2022, 4:02:31 AM

# Build Your Own Matchmaking Service with AccelByte Python SDK in AWS Lambda

# Overview

In this tutorial, you will learn how to build and customize your own Matchmaking service using AccelByte’s Python SDK. This guide will show you how to create a Matchmaking service where two players can play together. The implementation covered in this guide will flow as follows:.


# Prerequisites

# Initial Setup

# Authorization

  1. Authorize access to AccelByte’s API using the following steps:

    1. Ensure that you have created a User and a Game Client in the Admin Portal.
    2. Open the IAM Swagger page from the OAuth2 authorize API: /iam/v3/OAuth/authorize (opens new window). A Request ID will be generated.
    3. Log in using the user_name and password from the Authentication API: /iam/v3/authenticate (opens new window). Input the Request ID generated in the previous step. If the request succeeds, you will receive an authorization code which will be used in the next step.
    4. Generate the user token using the authorization code from the OAuth2 Access Token Generation: /iam/v3/oauth/token (opens new window). If the request succeeds, you will receive a user token which will be used in Step 2.
    5. Generate an OAuth Client token using client_credentials from the OAuth2 Access Token Generation: /iam/v3/oauth/token (opens new window). If the request succeeds, you will receive an OAuth Client token which will be used when implementing functions related to the DSMC.
  2. Validate the user’s request (opens new window) by extracting the authorization header value Bearer Auth Token from the user’s request.

    # 02. Extract the Bearer Auth Token from the Authorization header.
    authorization = str(event.get("headers").get("Authorization"))
    bearer_auth_token, error = extract_bearer_auth_token(authorization)
    if error:
        return error
    log_done("extract Bearer Auth Token")
  3. Convert the Bearer Auth Token (opens new window) you obtained into an instance of OauthmodelTokenResponseV3 (opens new window).

    # 03. Convert Bearer Auth Token into an OAuth Token object.
      oauth_token, error = convert_bearer_auth_token_to_oauth_token(bearer_auth_token)
      if error:
          return error
      log_done("convert Bearer Auth Token")
  4. Create a Redis client (opens new window) to connect to the Elasticache for Redis (opens new window) to store matchmaking requests.

    # 04. Create Redis Client.
      redis_client = create_redis_client(env.redis_host, env.redis_port)
      log_done(f"create redis client ({redact(f'{env.redis_host}:{env.redis_port}')})")
  5. Create an instance of an IAM Client (opens new window) of the IAM-Python-SDK and use it to validate the OAuth Token and its Permissions and Claims.

    # 05. Create IAM Client.
    iam_client = create_iam_client(env.iam_base_url, env.iam_client_id, env.iam_client_secret)
    log_done("create IAM client")
    # 06. Validate IAM Client locally.
    error = validate_iam_client_locally(iam_client)
    if error:
        return error
    log_done("validate IAM Client locally")
    # 07. Grant IAM Client an Access Token.
    error = grant_iam_client_access_token(iam_client)
    if error:
        return error
    log_done("grant IAM Client an Access Token")
    # 08. Validate Access Token.
    error = validate_access_token(iam_client, bearer_auth_token)
    if error:
        return error
    log_done("validate Access Token")
    # 09. Validate permissions.
    error = validate_permissions(iam_client, bearer_auth_token, oauth_token)
    if error:
        return error
    log_done("validate permissions")
    # 10. Parse and validate claims.
    claims, error = validate_claims(iam_client, bearer_auth_token)
    if error:
        return error
    log_done("parse and validate claims")
    user_id = claims.Sub
    namespace = claims.Namespace
  6. Initialize the AccelByte Python SDK (opens new window) and use it to store the OAuth Token.

    # 11. Initialize the AccelByte Python SDK.
    # 11.a. Create IAM ConfigRepository and TokenRepository
    iam_config_repo = MyConfigRepository(env.iam_base_url, env.iam_client_id, env.iam_client_secret)
    iam_token_repo = MyTokenRepository(oauth_token)
    # 11.b. Create Game ConfigRepository and TokenRepository
    game_config_repo = MyConfigRepository(env.game_base_url, env.game_client_id, env.game_client_secret, env.game_namespace)
    game_token_repo = MyTokenRepository(None)
    # 11.c. Store the 2 different pairs of repositories
    global IAM_REPO, GAME_REPO
    IAM_REPO = iam_config_repo, iam_token_repo
    GAME_REPO = game_config_repo, game_token_repo

# Tutorials

# Create a Matchmaking Request

Using your previously generated User ID, create a matchmaking request (opens new window) that contains a new channel and party.

  # 13. Create matchmaking request
  error = create_matchmaking_request(redis_client, namespace, env.game_mode, user_id)
  if error:
      return error
  log_done("create matchmaking request")

# Set Up Search Notifications

Set up a function to send a match search notification (opens new window) to the player via WebSockets. Players will receive this notification while waiting for a match.

# 14. Send search for match notification to user
    error = send_notif_match_searching(namespace, user_id)
    if error:
        return error
    log_done(f"send free form notification (match searching) to  player ({user_id})")

# Set Waiting Time

Set the maximum time (opens new window) the service will wait for another player while matchmaking.

# 15. Wait for another user.
    elapsed_time = 0.0
    active_matchmaking_requests_summary = None
    other_matchmaking_request = None
    while elapsed_time < FIND_OTHER_USER_MAX_DURATION:
        active_matchmaking_requests_summary, error = get_active_matchmaking_requests_summary(
        if error:
            return error
        other_matchmaking_request = active_matchmaking_requests_summary.get_other_matchmaking_request(user_id)
        if other_matchmaking_request:
        elapsed_time += FIND_OTHER_USER_CHECK_INTERVAL
        log_wait(f"waiting for other players.. {elapsed_time:.2f}/{FIND_OTHER_USER_MAX_DURATION:.2f}s")
    if not other_matchmaking_request:
        return create_response(408, "Timed out! Not enough players.")
    log_done(f"find other user ({other_matchmaking_request['user_id']})")

    party_id = other_matchmaking_request["party_id"]
    user_ids = list(active_matchmaking_requests_summary.unique_user_ids)
    other_user_ids = list(active_matchmaking_requests_summary.get_other_user_ids(user_id))

# Manage Game Session

# Create a Game Session in the Session Browser

In this section, we will be registering the game session to the session browser (opens new window). This step will also check whether there are enough players in the database. When the game has enough players, the game session will be registered in the session browser and a Session ID will be created. This ID will be used to register the session in the DSMC.

# 16. Create session
    sb_session, error = create_session(
    if error:
        return error
    log_done(f"create session on session browser")

    sb_session_id = sb_session.

# Register a Game Session to DSMC

Once you have successfully created a session, register it to the DSMC (opens new window).

# 17. Register session on DSMC
    _, error = register_session_on_dsmc(
    if error:
        return error
    log_done(f"create session on dsmc")

    # 17.a. Wait for DSMC to register the session

# Claim a Game Server

This function is used to claim a game server (opens new window) from the DSMC service.

# 18. Claim server
    _, error = claim_server(
    if error:
        return error
    log_done(f"claim server from dsmc")

# Add Players to the Game Session

This function adds players to the server in the Session browser (opens new window).

# 20. Add players to server in Session Browser

   for idx, uid in enumerate(user_ids):
       _, error = add_player_to_sb_sesion(env.game_namespace, sb_session_id, uid)

       if error:
           return error
       log_done(f"add player ({uid}) to session [{(idx + 1):02d}/{len(user_ids):02d}]")

# Get Session Update

After adding players to the Matchmaking session, create a function to obtain the latest session information and to check if the session is now able to be joined.

# 21. Get session update from Session Browser
    sb_session, error = get_session_from_session_browser(

    # 22. Check if session is joinable
    if not sb_session.joinable:
        return create_response(400, "Unable to join the session.")

# Set Up Matching Notification

This function sends a notification to all players that a match has been found and displays the server IP and port.

# 23. Send notification to all users
    for idx, uid in enumerate(user_ids):
        error = send_notif_match_found(namespace, server_ip, server_port, uid)
        if error:
            log_warn(f"failed to send free form notification (match found) to player ({uid}) [{(idx + 1):02d}/{len(user_ids):02d}]")
            log_done(f"send free form notification (match found) to  player ({uid}) [{(idx + 1):02d}/{len(user_ids):02d}]")

    response = {
        "message": f"successfully matchmade "
        "server": {
            "ip": server_ip,
            "port": server_port,
        "session": {
            "id": sb_session_id
        "users": [

# Testing the Matchmaking

In this section, you will learn how to run and test your Matchmaking service locally. You can test your service with your files. When is running, it will prompt the player to enter their username and password. Once authorized, sends a a matchmaking request invokes the Lambda function. When a match is found, listens to the notification service and sends a notification.

r =
            "Authorization": f"Bearer {access_token}"
    print(f"[done]: sent matchmaking request")
def print_wsm(message: str, tag: str, indent="| ", prefix="\n", suffix="\n"):
        message = "\n".join([f"{indent}{line}" for line in message.rstrip().splitlines(keepends=False)])

    async def on_message(message: str):
        print_wsm(message, "recv")

    scheme, uri = base_url.split("://")
    ws_uri = f"wss://{uri}/lobby"

    ws_client = Websockets2WSClient(


    await ws_client.connect()
    print("[done]: connect to websocket")

Now you can test your Matchmaking service. In the Python terminal, run the script and enter the player’s email and password. Once authorized, matchmaking will begin..


# Deploying the Matchmaking Function into AWS Lambda

To upload the Matchmaking function that you created to AWS Lambda, first ensure that you have filled in all of the required fields in the AWS SAM Template and have tested the SAM locally both in AWS SAM and Client.

  1. In your terminal, go to the root directory of aws-lambda (opens new window).

  2. Run the build (opens new window) using the following function:

    sam build --use-container

    You can find more detailed information about Deploying using the AWS SAM CLI (opens new window) in AWS’s Documentation.

  3. Deploy (opens new window) the application to the AWS Cloud using the following function:

    sam deploy --guided

    Follow the on-screen prompts. You can find more detailed information about Deploying serverless applications (opens new window) in AWS’s Documentation.