Skip to content

WebSocket Events: Custom Events

Custom events are the heart of any real-time WebSocket application. They define the actions and behaviors your system supportsβ€”such as messaging, notifications, typing indicators, room management, and more.

This page shows how to design, name, and structure custom events consistently.


🧾 1. What Are Custom Events?

Custom events are user-defined type values in your WebSocket message format. These represent actions or updates within your application logic.

Example:

{
  "type": "user_typing",
  "data": {
    "room_id": "abc123",
    "user_id": "user456"
  }
}

πŸ“š 2. Event Naming Conventions

Use snake_case or kebab-case for consistency. Prefix events based on function or domain when appropriate.

Event Type Description
send_message User sends a chat message
new_message Server broadcasts new message
user_typing Indicates a user is typing
user_joined A user entered a room/channel
user_left A user disconnected or left a room
update_profile User updates their profile info
reaction_added User adds emoji reaction

Avoid overly generic names like event1, update, or message.


✍️ 3. Sample Event Definitions

πŸ“¨ Send Chat Message

Client β†’ Server:

{
  "type": "send_message",
  "data": {
    "room_id": "room-abc",
    "message": "Hello, world!"
  }
}

Server β†’ All Clients:

{
  "type": "new_message",
  "data": {
    "room_id": "room-abc",
    "user_id": "user123",
    "message": "Hello, world!",
    "timestamp": "2025-08-04T12:34:56Z"
  }
}

✍️ Typing Indicator

Client β†’ Server:

{
  "type": "user_typing",
  "data": {
    "room_id": "room-abc",
    "user_id": "user123"
  }
}

Server β†’ Other Clients:

{
  "type": "user_typing",
  "data": {
    "room_id": "room-abc",
    "user_id": "user123"
  }
}

πŸ™‹ User Join/Leave Notifications

Join:

{
  "type": "user_joined",
  "data": {
    "room_id": "room-abc",
    "user_id": "user123",
    "username": "johndoe"
  }
}

Leave:

{
  "type": "user_left",
  "data": {
    "room_id": "room-abc",
    "user_id": "user123"
  }
}

πŸ›  4. Backend Routing of Custom Events

Use a dispatcher or router to handle incoming type fields.

Example (Python)
event_handlers = {
    "send_message": handle_send_message,
    "user_typing": handle_user_typing,
    "update_profile": handle_update_profile,
}

async def handle_message(message: dict, websocket):
    event_type = message.get("type")
    handler = event_handlers.get(event_type)

    if handler:
        await handler(message["data"], websocket)
    else:
        await websocket.send_json({
            "type": "error",
            "data": {"message": f"Unsupported event: {event_type}"}
        })

βœ… Best Practices

  • Validate payloads per event type (e.g., using Pydantic or JSON Schema).
  • Broadcast efficiently using rooms, channels, or groups.
  • Document each event and its expected data shape.
  • Avoid overloading one event type with multiple functions.
  • Version carefully if events change shape over time.

πŸ§ͺ Event Testing Tips

  • Use Postman or browser dev tools with raw WebSocket clients.
  • Mock client messages to simulate edge cases.
  • Log unhandled type values on the server.
  • Add integration tests to verify each custom event’s round trip.

πŸ”š Next Steps

  • Clients: Learn how to emit and handle custom events in the frontend.
  • Message Format: Review the standard envelope used in all events.
  • Error Handling: Gracefully manage unknown or malformed event types.