Home   system-design  

System design for Whatsapp - System design interview

Designing a messaging app similar to WhatsApp involves several key components and considerations. Below is a high-level overview of the components and the tech stack involved, along with some simplified code snippets to illustrate basic concepts.

Components of a WhatsApp-like App

  1. Backend Server

    • Manages user authentication, message storage, and delivery.
    • Tech Stack: Node.js, Express.js, MongoDB or PostgreSQL (for message storage), WebSocket for real-time communication.
  2. Database

    • Stores user profiles, contacts, and messages.
    • Tech Stack: MongoDB or PostgreSQL for relational data storage.
  3. Authentication

    • Registers users, manages login/logout.
    • Tech Stack: JSON Web Tokens (JWT) for authentication, bcrypt for password hashing.
  4. Messaging

    • Handles real-time message delivery and synchronization across devices.
    • Tech Stack: WebSocket (socket.io) for real-time communication.
  5. Frontend Client (Mobile and Web)

    • Provides user interface for chatting, contacts management, and notifications.
    • Tech Stack: React Native for mobile app, React.js for web app, Redux or Context API for state management.
  6. Push Notifications

    • Sends notifications for incoming messages and other updates.
    • Tech Stack: Firebase Cloud Messaging (FCM) for Android, Apple Push Notification Service (APNs) for iOS.
  7. Encryption

    • Ensures end-to-end encryption of messages for privacy.
    • Tech Stack: Signal Protocol (used by WhatsApp), libraries like CryptoJS for encryption.

Low-Level Overview and Sample Code

Here's a simplified outline with sample code snippets for key components:

Backend Server (Node.js with Express)

  1. User Authentication and Registration

    const express = require('express');
    const bcrypt = require('bcrypt');
    const jwt = require('jsonwebtoken');
    const User = require('./models/User');
    
    const app = express();
    const secretKey = 'your_secret_key';
    
    // Register a new user
    app.post('/api/register', async (req, res) => {
        try {
            const { username, password } = req.body;
            const hashedPassword = await bcrypt.hash(password, 10);
            const newUser = new User({ username, password: hashedPassword });
            await newUser.save();
            res.status(201).json({ message: 'User registered successfully' });
        } catch (err) {
            res.status(500).json({ error: err.message });
        }
    });
    
    // User login
    app.post('/api/login', async (req, res) => {
        try {
            const { username, password } = req.body;
            const user = await User.findOne({ username });
            if (!user) {
                return res.status(404).json({ message: 'User not found' });
            }
            const isMatch = await bcrypt.compare(password, user.password);
            if (!isMatch) {
                return res.status(401).json({ message: 'Invalid credentials' });
            }
            const token = jwt.sign({ userId: user._id }, secretKey, { expiresIn: '1h' });
            res.json({ token });
        } catch (err) {
            res.status(500).json({ error: err.message });
        }
    });
    
    app.listen(3000, () => {
        console.log('Server started on port 3000');
    });
    
  2. Message Handling with WebSocket

    const WebSocket = require('ws');
    const wss = new WebSocket.Server({ port: 8080 });
    
    wss.on('connection', (ws) => {
        console.log('Client connected');
    
        ws.on('message', (message) => {
            console.log(`Received message: ${message}`);
            // Process and store message in database
            ws.send('Message received');
        });
    
        ws.on('close', () => {
            console.log('Client disconnected');
        });
    });
    

Frontend Client (React Native)

  1. Messaging Screen

    import React, { useEffect, useState } from 'react';
    import { View, Text, TextInput, Button } from 'react-native';
    import io from 'socket.io-client';
    
    const socket = io('http://localhost:8080');
    
    const MessagingScreen = () => {
        const [message, setMessage] = useState('');
        const [receivedMessage, setReceivedMessage] = useState('');
    
        useEffect(() => {
            socket.on('message', (data) => {
                setReceivedMessage(data);
            });
        }, []);
    
        const sendMessage = () => {
            socket.emit('message', message);
            setMessage('');
        };
    
        return (
            <View>
                <Text>Received message: {receivedMessage}</Text>
                <TextInput
                    value={message}
                    onChangeText={setMessage}
                    placeholder="Type your message"
                />
                <Button title="Send" onPress={sendMessage} />
            </View>
        );
    };
    
    export default MessagingScreen;
    

Considerations

Published on: Jul 10, 2024, 01:46 AM  
 

Comments

Add your comment