Reducing polling load with ETag and conditional requests

Backend Live Coding November 13, 2026 python

Conditional requests with ETag.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ======================================================================
# Q: Thousands of players ask every few minutes "has anything changed?". How do
# you reduce the load?
#
# Conditional requests with ETag. The player sends If-None-Match, and if nothing
# has changed I answer 304 with no body. I derive the ETag from a cheap field
# (e.g. the playlist's updated_at or content_version), so I don't need to build
# the whole response to compute it. It can also be kept in Redis so it doesn't
# even hit the database.
# Alternatively, push instead of poll: WebSocket (Django Channels) or MQTT,
# where the server notifies only when there is a change. You usually keep a poll
# with a long interval as a fallback too, because screen connections drop.
# ======================================================================

class PlayerManifestView(APIView):
    authentication_classes = [DeviceTokenAuthentication]

    def get(self, request):
        screen = request.auth.screen
        etag = f'"{screen.playlist_id}-{screen.playlist.content_version}"'
        if request.headers.get('If-None-Match') == etag:
            return Response(status=304)
        data = build_manifest(screen)          # the heavy part
        return Response(data, headers={'ETag': etag, 'Cache-Control': 'private, no-cache'})