POST request triggering WebSocket send

Hello everyone,
I have a project where I need to receive data from a POST request, save it to the database and then send the database content to a websocket. This works completely fine when I use the django development server.
But as soon as I use a production environment (nginx, uwsgi and daphne) the data does not get sent to the websocket. Saving to the database works fine, it just does not get sent.
Also, when receiving over the websocket I can send without any problems in the production environment. It’s just the problem with receiving over a POST request and then sending to the websocket.
Why could that be? Here is my code:

views.py

from django.shortcuts import render
from django.template.loader import render_to_string
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.utils import timezone
from datetime import datetime
from .models import Loesung

def loesungsUpdate():
    loesungen = Loesung.objects.all()
    if loesungen:
        for i in loesungen:
            i.abgabezeit = datetime.fromisoformat(str(i.abgabezeit)).astimezone(timezone.get_current_timezone()).strftime("%d.%m.%Y, %H:%M")
        loesungen = render_to_string('mathenacht/partials/loesungsuebersichtUpdate.html', {'loesungen':loesungen})
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            'loesungsuebersicht', {
                'type': 'loesungsuebersichtUpdateHandler', # Handler must be in consumers.py
                'loesungen': loesungen,
            }
        )

consumers.py

from channels.generic.websocket import WebsocketConsumer
from asgiref.sync import async_to_sync
from django.template.loader import render_to_string
from django.utils import timezone
from datetime import datetime
import json
from .models import Loesung

class mathenachtConsumer(WebsocketConsumer):
    def connect(self):
        async_to_sync(self.channel_layer.group_add)( # Add the connecting user to a 'backend' chatroom so that everyone receives every message
            'loesungsuebersicht', self.channel_name # chatroom as a hardcoded name for the chatroom, self.channel_name gets auto filled from Django and is tied to the user
        )
        self.accept()

    def disconnect(self, code):
        async_to_sync(self.channel_layer.group_discard)( # Remove the user from that chatroom
            'loesungsuebersicht', self.channel_name
        )
    
    def receive(self, text_data):
        ...

    def loesungsuebersichtUpdateHandler(self, event):
        self.send(text_data=event['loesungen'])

I removed the code from the receive function in consumers.py because it is long and not necessary for the problem (i think :sweat_smile:).

I am happy to give more information if needed. Thanks in advance.

What channel layer are you using?

(What’s the CHANNEL_LAYERS setting from your settings.py file?)

My channel layer config looks like this:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer',
    },
}

I know that I should probably be using redis or something else than the InMemoryChannelLayer in production, but I didn’t want to make it more complicated than necassary since this is only a small project that is only used by a handful of people.

You don’t really have a choice.

Read the docs for In-Memory Channel Layer, including the orange warning box.

Ok, so what I’m trying to do would work with something like redis? If so, then I guess I have to switch. Is redis the option you would recommend or would that be something else?

Redis is the easiest way. (I’m actually not aware of any other known, good, channel layer implementations using any other stack.) If you don’t want to use redis itself, I know that Valkey also works. (I’d assume that any of the other redis forks would probably work as well.)

Ok, then I will try that later. Thanks for your help until now!

I have redis now installed with the following steps:
pip install channels-redis
sudo apt install redis
I replaced the default CHANNEL_LAYERS in settings.py with

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

and it does not work yet. Have I forgotten anything? I do not get any errors and it is working fine just as before with the development server.

You restarted both the uwsgi and daphne services?

If so, the next step would be to verify that the data is passing through the channel layer to the consumers. One of the easiest ways to do that is to use something like tcpdump or wireshark to monitor port 6379. You should see packets being generated from one of your uwsgi processes being sent to redis, and then those packets being distributed from redis to your daphne process.

I did not. :joy:
Just to make sure I just rebooted the entire server and it is working now. Thanks a lot for you help! And to be honest, redis is probably the better option regardless and in hindsight it was not hard to install either. :sweat_smile:
I will mark your answer, where you said I should use redis, as the solution.