Message patterns¶
This page describes common messaging patterns used with Django-AWS-API-Gateway-WebSockets.
The package supports sending messages from Django to connected WebSocket clients through AWS API Gateway.
Common patterns include:
replying to the current connection;
sending to one stored session;
sending to all sessions for a user;
sending to all sessions in a channel;
broadcasting to all connected sessions;
sending toast notifications;
sending task progress updates;
sending lightweight invalidation messages;
handling stale connections.
Overview¶
AWS API Gateway owns the WebSocket connection.
Django sends messages back to clients using the API Gateway Management API.
The package provides two main ways to send messages:
WebSocketSession.send_message()Send to one specific WebSocket connection.
WebSocketSession.objects.filter(...).send_message()Send to all connected sessions in a queryset.
The queryset version sends to connected sessions in the queryset.
Message shape¶
Messages should be JSON-compatible dictionaries.
A useful convention is to include a type field.
Example:
{
"type": "notification",
"message": "You have a new notification.",
}
The frontend can then switch behaviour based on type.
Example browser handler:
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.type === "notification") {
showNotification(data.message);
return;
}
if (data.type === "chat_message") {
appendChatMessage(data.username, data.message);
return;
}
console.log("Unhandled message:", data);
};
Recommended message fields¶
Common fields include:
typeThe kind of message being sent.
messageHuman-readable text.
levelSeverity or style, such as
success,info,warning, orerror.idApplication object ID.
created_atTimestamp.
channelChannel or room name.
payloadStructured data for the client.
Example:
{
"type": "chat_message",
"channel": "general",
"username": "alice",
"message": "Hello everyone",
"created_at": "2026-04-30T12:00:00Z"
}
Send to one stored session¶
You can also send to a specific stored WebSocketSession.
Example:
from django_aws_api_gateway_websockets.models import WebSocketSession
session = WebSocketSession.objects.get(pk=1)
session.send_message(
{
"type": "notification",
"message": "This message was sent to one connection.",
}
)
This is useful when you have stored or looked up a specific session.
Send to a user’s active sessions¶
A user may have multiple active WebSocket sessions, such as multiple browser tabs or devices.
You can send a message to all active sessions for one user.
from django.contrib.auth import get_user_model
User = get_user_model()
user = User.objects.get(username="alice")
user.websocket_sessions.filter(
connected=True,
).send_message(
{
"type": "notification",
"message": "This message was sent to all of Alice's active sessions.",
}
)
Send to a channel¶
Channels are used to group WebSocket sessions.
Example use cases:
chat rooms;
dashboards;
tenant updates;
project updates;
document collaboration;
notification streams.
Example:
from django_aws_api_gateway_websockets.models import WebSocketSession
WebSocketSession.objects.filter(
channel_name="general",
).send_message(
{
"type": "chat_message",
"channel": "general",
"username": "alice",
"message": "Hello general room.",
}
)
This sends the message to active sessions in the general channel.
Broadcast to all connected sessions¶
Broadcasting sends a message to all active WebSocket sessions.
Example use cases:
maintenance warnings;
system-wide announcements;
incident notices;
global feature flags or reload notices.
Example:
from django_aws_api_gateway_websockets.models import WebSocketSession
WebSocketSession.objects.filter(
connected=True,
).send_message(
{
"type": "system",
"level": "warning",
"message": "Maintenance will begin in 5 minutes.",
}
)
Use broadcast carefully. Large or frequent broadcasts may increase AWS usage and application load.
Send a toast notification¶
Toast notifications are a common WebSocket pattern.
Server-side example:
self.websocket_session.send_message(
{
"type": "toast",
"level": "success",
"title": "Saved",
"message": "Your changes have been saved.",
}
)
Frontend example:
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.type === "toast") {
showToast(data.level, data.title, data.message);
return;
}
};
function showToast(level, title, message) {
console.log(`[${level}] ${title}: ${message}`);
}
Toast payloads commonly include:
type;level;title;message;optional timeout;
optional action URL.
Send task progress¶
WebSockets are useful for showing progress from long-running work.
Example server-side message:
WebSocketSession.objects.filter(
channel_name="task_123",
).send_message(
{
"type": "task_progress",
"task_id": 123,
"percent": 75,
"message": "Processing records.",
}
)
Frontend handler:
socket.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.type === "task_progress") {
updateProgressBar(data.task_id, data.percent, data.message);
return;
}
};
For long-running background jobs, a common pattern is:
create a channel for the task;
connect the browser to that channel;
send progress updates to the channel;
send a completion message when finished.
Send lightweight invalidation messages¶
For larger data updates, avoid sending the full data over WebSocket.
Instead, send a small invalidation message and let the browser fetch the updated data over HTTPS.
Example:
WebSocketSession.objects.filter(
channel_name="dashboard",
).send_message(
{
"type": "resource_updated",
"resource": "order",
"id": 123,
"fetch_url": "/api/orders/123/",
}
)
Frontend:
socket.onmessage = async function (event) {
const data = JSON.parse(event.data);
if (data.type === "resource_updated") {
const response = await fetch(data.fetch_url);
const resource = await response.json();
updatePage(resource);
}
};
This keeps WebSocket messages small and avoids duplicating normal HTTP API behaviour.
Chat room message¶
A typical chat message pattern is:
browser sends a message to Django;
Django validates and stores the message;
Django sends the message to all sessions in the same channel.
Example:
from django.http import JsonResponse
from django_aws_api_gateway_websockets.models import WebSocketSession
from django_aws_api_gateway_websockets.views import WebSocketView
class ChatWebSocketView(WebSocketView):
def chat_message(self, request, *args, **kwargs):
room = self.websocket_session.channel_name
text = self.body.get("message", "").strip()
if not text:
return JsonResponse(
{
"ok": False,
"error": "Message cannot be empty.",
},
status=400,
)
WebSocketSession.objects.filter(
channel_name=room,
).send_message(
{
"type": "chat_message",
"room": room,
"username": request.user.get_username(),
"message": text,
}
)
return JsonResponse({"ok": True})
See Full chat room example for a fuller chat room example.
Admin broadcast¶
A systems administrator can broadcast from the Django shell.
python manage.py shell
Then:
from django_aws_api_gateway_websockets.models import WebSocketSession
WebSocketSession.objects.filter(
connected=True,
).send_message(
{
"type": "system",
"level": "warning",
"message": "Maintenance will begin in 5 minutes.",
}
)
Message size limits¶
AWS API Gateway WebSocket messages have size limits.
Keep messages compact.
Recommended patterns:
send IDs instead of full objects;
send URLs for the browser to fetch larger data;
avoid sending large lists;
avoid sending binary data directly;
compress or paginate data through normal HTTP APIs if needed.
Good WebSocket message:
{
"type": "report_ready",
"report_id": 123,
"fetch_url": "/reports/123/"
}
Poor WebSocket message:
{
"type": "report_ready",
"rows": [
"thousands of rows of data"
]
}
Handling stale connections¶
Clients may disconnect unexpectedly.
When sending a message, AWS may report that a connection is gone.
This can happen when:
a browser tab closes;
a laptop sleeps;
a mobile network changes;
API Gateway times out the connection;
a stale session remains in the database.
Treat stale connections as normal operational behaviour.
Schedule cleanup:
python manage.py clearWebSocketSessions
See Clean-up.
Security considerations¶
Validate incoming messages¶
Do not trust client payloads.
Validate:
required fields;
string lengths;
object IDs;
user permissions;
channel access;
message type;
allowed actions or handlers.
Do not trust channel names¶
A client can request a channel name.
Always check whether the user is allowed to use that channel.
Avoid sensitive data in messages¶
Only send data the connected user is allowed to see.
If broadcasting or multicasting, confirm that every recipient should receive the message.
Use permissions¶
Use Django permissions and object-level checks where needed.
See Permissions.
Recommended message conventions¶
A consistent message format makes frontend code easier to maintain.
Suggested base shape:
{
"type": "message_type",
"payload": {}
}
Example:
{
"type": "toast",
"payload": {
"level": "success",
"title": "Saved",
"message": "Your changes have been saved."
}
}
Or, for smaller projects, a flatter shape is fine:
{
"type": "toast",
"level": "success",
"title": "Saved",
"message": "Your changes have been saved."
}
Choose one convention and use it consistently.
Testing message patterns¶
When testing message patterns:
mock AWS API Gateway Management API calls;
test unicast sends;
test channel sends;
test broadcasts;
test permission failures;
test stale connection handling;
test message size behaviour;
test frontend handling of each
type.
See Testing.