---
title: "Building a Production-Grade Chat Application with ASP.NET Core, SignalR, Redis, and React"  
description: "Building a production-grade chat platform capable of handling thousands of concurrent users, real-time messaging, message persistence, scalability, security, an"  
author: "Ravi Vishwakarma"  
published: 2026-05-30  
updated: 2026-05-30  
canonical: https://answers.mindstick.com/blog/332/building-a-production-grade-chat-application-with-asp-dot-net-core-signalr-redis-and-react  
category: "software"  
tags: ["software", "chatgpt"]  
reading_time: 6 minutes  

---

# Building a Production-Grade Chat Application with ASP.NET Core, SignalR, Redis, and React

## Introduction

Building a basic chat application is relatively simple. Building a production-grade chat platform capable of handling thousands of concurrent users, real-time messaging, message persistence, scalability, security, and fault tolerance is an entirely different challenge.

In this guide, we'll build a modern chat application using:

- [ASP.NET Core](https://www.mindstick.com/articles/326150/asp-dot-net-core-why-it-is-best-suited-for-banking-and-finance-sectors) 9
- SignalR
- [Entity Framework](https://www.mindstick.com/articles/1566/crud-operations-using-entity-framework-code-first-approach) Core
- [SQL Server](https://www.mindstick.com/articles/34/create-table-in-microsoft-sql-server)
- Redis
- JWT Authentication
- React
- Docker
- Azure/AWS Deployment

## What Makes a Chat Application Production Grade?

Most tutorials stop after [sending messages](https://answers.mindstick.com/qa/95290/why-is-my-telegram-not-sending-messages) between two browsers.

A production system requires:

- Authentication
- User Presence
- [Private Messaging](https://www.mindstick.com/interview/34154/how-do-you-implement-private-messaging-between-two-users-in-a-signalr-chat-application)
- Group Chats
- Message Persistence
- Offline Messages
- Read Receipts
- Typing Indicators
- Scalability
- Monitoring
- Security
- Rate Limiting
- Distributed Architecture

## Final Architecture

```plaintext
React Frontend
       │
       ▼
ASP.NET Core API
       │
       ├── JWT Authentication
       ├── SignalR Hub
       ├── Message Service
       └── User Presence Service
              │
              ▼
Redis Backplane
              │
              ▼
SQL Server
```

## Step 1: Create Solution Structure

Create separate projects.

```plaintext
ChatApp
│
├── ChatApp.API
├── ChatApp.Application
├── ChatApp.Domain
├── ChatApp.Infrastructure
└── ChatApp.Tests
```

Benefits:

- Clean Architecture
- Separation of concerns
- Easier testing
- Better maintainability

## Step 2: Design Database Schema

## Users

```plaintext
CREATE TABLE Users
(
    Id UNIQUEIDENTIFIER PRIMARY KEY,
    Username NVARCHAR(100),
    Email NVARCHAR(200)
)
```

## Conversations

```plaintext
CREATE TABLE Conversations
(
    Id UNIQUEIDENTIFIER PRIMARY KEY,
    CreatedAt DATETIME2
)
```

## Messages

```plaintext
CREATE TABLE Messages
(
    Id UNIQUEIDENTIFIER PRIMARY KEY,
    ConversationId UNIQUEIDENTIFIER,
    SenderId UNIQUEIDENTIFIER,
    Content NVARCHAR(MAX),
    SentAt DATETIME2,
    IsRead BIT
)
```

Indexes:

```plaintext
CREATE INDEX IX_Messages_ConversationId
ON Messages(ConversationId)
```

Without indexing, message retrieval becomes a bottleneck.

## Step 3: Implement JWT Authentication

Install:

```plaintext
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
```

Configure JWT.

```cs
builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters =
            new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true
            };
    });
```

- Why JWT?
- Stateless
- Scalable
- Cloud-friendly
- Mobile-friendly

## Step 4: Configure SignalR

Install package:

```plaintext
dotnet add package Microsoft.AspNetCore.SignalR
```

Create Hub:

```cs
public class ChatHub : Hub
{
    public async Task SendMessage(
        string conversationId,
        string message)
    {
        await Clients.Group(conversationId)
            .SendAsync("ReceiveMessage", message);
    }
}
```

Register:

```cs
app.MapHub<ChatHub>("/chatHub");
```

Now clients [receive messages](https://answers.mindstick.com/qa/113102/why-can-t-i-send-or-receive-messages-on-whatsapp) instantly.

## Step 5: Persist Messages

A common beginner mistake:

- Messages exist only in memory.
- Production systems always persist messages.

```cs
public async Task SaveMessageAsync(Message message)
{
    _db.Messages.Add(message);

    await _db.SaveChangesAsync();
}
```

Benefits:

- History
- Auditing
- Offline access
- Compliance

## Step 6: Create Conversation Management

Users need chat rooms.

```cs
public async Task JoinConversation(
    string conversationId)
{
    await Groups.AddToGroupAsync(
        Context.ConnectionId,
        conversationId);
}
```

SignalR groups make room-based messaging easy.

## Step 7: Add User Presence Tracking

Users expect online indicators.

Store active connections.

```cs
ConcurrentDictionary<Guid,string>
```

Track:

- Online
- Offline
- Last Seen
- Broadcast updates.

```cs
await Clients.All
    .SendAsync("UserOnline", userId);
```

## Step 8: Implement Typing Indicators

Modern chat applications display typing status.

```cs
public async Task Typing(
    string conversationId)
{
    await Clients.Group(conversationId)
        .SendAsync(
            "UserTyping",
            Context.UserIdentifier);
}
```

This dramatically improves [user experience](https://www.mindstick.com/articles/12731/the-importance-of-feedback-to-the-user-experience).

## Step 9: Read Receipts

Store message status.

```cs
public bool IsRead { get; set; }
```

When users open a conversation:

```cs
message.IsRead = true;
```

Notify sender:

```cs
await Clients.User(senderId)
    .SendAsync("MessageRead");
```

## Step 10: Handle Offline Messages

Real users disconnect frequently.

Never assume users remain connected.

Workflow:

- Save message
- Check recipient status
- Deliver immediately if online
- Queue if offline

When reconnecting:

```cs
LoadUnreadMessages()
```

This ensures message reliability.

## Step 11: Scale with Redis

Single-server SignalR works fine initially.

Problems occur when:

- [Multiple servers](https://www.mindstick.com/articles/334280/load-distribution-strategies-distributing-incoming-traffic-across-multiple-servers) exist
- Load balancing is introduced
- Install Redis package.

```plaintext
dotnet add package Microsoft.AspNetCore.SignalR.StackExchangeRedis
```

Configure:

```cs
builder.Services
    .AddSignalR()
    .AddStackExchangeRedis(
        "localhost:6379");
```

Redis synchronizes messages across servers.

## Step 12: Add Rate Limiting

Protect against spam.

```cs
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter(
        "chat",
        config =>
        {
            config.PermitLimit = 50;
        });
});
```

Benefits:

- Prevent abuse
- Protect infrastructure
- Improve stability

## Step 13: Secure the Application

Security checklist:

### Validate Inputs

```cs
message.Length <= 2000
```

### Prevent XSS

Sanitize user content.

### Encrypt Connections

Use HTTPS only.

### Secure Secrets

Never store secrets in source control.

Use:

- Azure Key Vault
- AWS Secrets Manager

## Step 14: Add Logging

Install Serilog.

```plaintext
dotnet add package Serilog.AspNetCore
```

Log:

- Connections
- Disconnections
- Errors
- Authentication failures

Example:

```cs
_logger.LogInformation(
    "User connected: {UserId}",
    userId);
```

Logs are critical for troubleshooting.

## Step 15: Monitor Performance

Production systems need observability.

Track:

- Message delivery latency
- Failed messages
- Active users
- CPU
- Memory

Recommended tools:

- OpenTelemetry
- Grafana
- Prometheus
- Application Insights

## Step 16: Dockerize Everything

Dockerfile:

```plaintext
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app

COPY . .

ENTRYPOINT ["dotnet","ChatApp.API.dll"]
```

Benefits:

- Consistent deployments
- Easier scaling
- Cloud portability

## Step 17: Deploy to Cloud

Recommended deployment:

```plaintext
Azure App Service
        │
Azure Redis Cache
        │
Azure SQL Database
        │
Application Insights
```

Alternative:

```plaintext
AWS ECS
    │
ElastiCache Redis
    │
RDS SQL Server
```

## Step 18: Load Testing

Before launch:

Use:

- k6
- JMeter
- Locust

Test:

- 1,000 users
- 10,000 users
- Peak traffic

Measure:

- Latency
- Throughput
- Resource usage

## Step 19: Add Advanced Features

Once the core system is stable:

### Message Reactions

👍 ❤️ 🔥

### File Uploads

- Images
- Videos
- Documents

### Voice Messages

Audio recording support

### Push Notifications

Mobile alerts

### End-to-End Encryption

Enhanced privacy

## Common Production Mistakes

Avoid:

- Storing messages in memory
- No authentication
- No monitoring
- No Redis scaling
- No indexing
- No rate limiting
- Logging sensitive data
- Ignoring load testing

## Conclusion

Building a production-grade chat application involves much more than sending messages between connected users. A reliable system must address scalability, persistence, security, observability, fault tolerance, and user experience.

By combining ASP.NET Core, SignalR, Redis, SQL Server, JWT authentication, and modern [cloud](https://www.mindstick.com/services/cloud-development) infrastructure, you can create a messaging platform capable of supporting real-world workloads while maintaining high performance and reliability.

The techniques covered in this guide mirror the architecture patterns used by many modern messaging platforms and provide a [strong foundation](https://answers.mindstick.com/qa/102922/how-to-build-a-strong-foundation-in-a-new-subject) for building enterprise-ready real-time applications.

---

Original Source: https://answers.mindstick.com/blog/332/building-a-production-grade-chat-application-with-asp-dot-net-core-signalr-redis-and-react

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
