Basics of designing a simple social network architecture

Social networks have become an integral part of our daily lives. They bring people together, allow them to exchange information, keep in touch with friends and even find new acquaintances. However, behind all these capabilities lies the complex engineering work of creating and maintaining social platforms.

This article will walk you through the basics of designing a simple social network architecture. Whether you’re an experienced developer, just starting out in the field, or just curious about how social networks work under the hood, you’ll find useful tips and examples here.

A bit of requirements analysis

  1. Functional requirements

    Before we start designing the architecture of our social network, we need to clearly define the functional requirements:

    • Registration and Authentication: What registration methods will be provided to users (for example, via social networks or email)? How will users be authenticated?

    • User Profiles: What data will be stored in user profiles? How can users customize their profiles?

    • Content creation and management: How can users create and publish content (text, photos, videos)? How will access to content be managed?

    • Social connections: How can users establish connections with each other (friends, followers)? What interaction features will be provided?

    • Notifications: What notifications will be sent to users (for example, notifications about new messages or posts from friends)?

  2. Non-functional requirements

    In addition to functional requirements, it is necessary to consider non-functional aspects that affect the quality and performance of the system. Here are some of them:

    • Scalability: A network can have millions of users, so the system must be able to scale horizontally as needed.

    • Safety: What security measures will be implemented to protect user data and the system from external attacks?

    • Performance: The system must provide high performance so that users can quickly access content and interact with each other.

    • Availability: The network must be available 24/7 and measures must be in place to minimize downtime.

Architecture design

Designing an architecture for a social network begins with a conscious choice of technology stack:

  1. Database

    • SQL (relational databases): Examples – PostgreSQL, MySQL, SQLite.

      Advantages:

      • Structured data and the ability to maintain data integrity.

      • Complex queries for analysis and reporting.

      • Suitable for applications where data has a rigid structure, such as user profiles and social connections.

    • NoSQL (non-relational databases): Examples – MongoDB, Cassandra, Redis.

      Advantages:

      • Flexible data structure, well suited for storing heterogeneous information, for example, news feeds.

      • Scalability and high performance for large volumes of data.

      • Ability to quickly add new fields and data types.

    When designing our social network architecture, we can use a hybrid approach, combining relational and non-relational databases depending on specific needs.

    Creating a user table in PostgreSQL:

    CREATE TABLE users (
        user_id SERIAL PRIMARY KEY,
        username VARCHAR(255) NOT NULL,
        email VARCHAR(255) NOT NULL UNIQUE,
        password_hash VARCHAR(255) NOT NULL
    );
    

    Sample code to add a user to MongoDB:

    db.users.insert({
        username: "example_user",
        email: "user@example.com",
        password_hash: "hashed_password"
    });
    
  2. Programming languages

    The choice of programming language is also important. Programming languages ​​that are widely used in the development of social networks:

    • Python: Python provides many web development frameworks such as Django and Flask. It is known for its simplicity and readability of code.

    • JavaScript: JavaScript is used for frontend and backend development using Node.js. It allows you to create interactive web applications.

    • Java: Java is often used in large social networks due to its scalability and reliability.

    Sample code for creating a simple web server in Node.js using Express:

    const express = require("express");
    const app = express();
    
    app.get("/", (req, res) => {
        res.send("Привет, мир!");
    });
    
    app.listen(3000, () => {
        console.log("Сервер запущен на порту 3000");
    });
    
  3. Frameworks and libraries

    Frameworks and libraries significantly speed up the development process and provide project structure. Here are some popular frameworks and libraries:

    • Django: A Python framework that provides many tools for developing social networks, including authentication and an administrative interface.

    • React: A JavaScript library for creating interactive user interfaces that can be used for the front end of a social network.

    • Express: A minimalistic Node.js framework for creating fast and scalable web applications.

    • Socket.IO: A library for implementing real-time chat and notifications.

    The choice of technology stack depends on the requirements for your social network and your preferences. This stack will determine how easy it is to develop, scale, and maintain your platform.

Database structure

A reliable and optimized database provides efficient storage and access to user data, relationships, content and more. This is how you can organize a database for our social network:

  1. Users and profiles

    Users are the central link of any social network. To store information about users, their profiles and settings, we can create a table users or collection users, depending on the selected database. Example structure for a table users:

    CREATE TABLE users (
        user_id SERIAL PRIMARY KEY,
        username VARCHAR(255) NOT NULL,
        email VARCHAR(255) NOT NULL UNIQUE,
        password_hash VARCHAR(255) NOT NULL,
        bio TEXT,
        profile_picture_url VARCHAR(255),
        registration_date TIMESTAMP DEFAULT NOW()
    );
    

    In this table we store user information such as username (username), E-mail address (email), password hash (password_hash), biography (bio), profile photo URL (profile_picture_url) and registration date (registration_date).

    Code to insert a new user into the table:

    INSERT INTO users (username, email, password_hash)
    VALUES ('john_doe', 'john@example.com', 'hashed_password');
    
  2. Friends and connections between users

    We can use additional tables or collections to store information about friends, subscribers, and subscriptions.

    For example, to store a list of users’ friends, we can create a table user_friends:

    CREATE TABLE user_friends (
        user_id INT,
        friend_id INT,
        PRIMARY KEY (user_id, friend_id),
        FOREIGN KEY (user_id) REFERENCES users (user_id),
        FOREIGN KEY (friend_id) REFERENCES users (user_id)
    );
    

    In this table, each entry represents a relationship between a user (user_id) and his friend (friend_id).

    Code for adding a friend for a user with user_id = 1:

    INSERT INTO user_friends (user_id, friend_id)
    VALUES (1, 2);
    
  3. Publications and content

    We can create a table to store information about publications posts:

    CREATE TABLE posts (
        post_id SERIAL PRIMARY KEY,
        user_id INT,
        content TEXT,
        created_at TIMESTAMP DEFAULT NOW(),
        FOREIGN KEY (user_id) REFERENCES users (user_id)
    );
    

    In this table, each entry represents one publication containing information about the user (user_id), text content (content) and creation date (created_at).

    Code for creating a new post from a user with user_id = 1:

    INSERT INTO posts (user_id, content)
    VALUES (1, 'Привет, мир! Это моя первая публикация.');
    
  4. Newsline and feeds

    To create a news feed for users and their feeds (feeds of content from friends), you can use different approaches. One common method is tape caching and precomputation. For example we can use a table news_feed to store already prepared entries in the feed:

    CREATE TABLE news_feed (
        user_id INT,
        post_id INT,
        created_at TIMESTAMP DEFAULT NOW(),
        FOREIGN KEY (user_id) REFERENCES users (user_id),
        FOREIGN KEY (post_id) REFERENCES posts (post_id)
    );
    

    In this table we can store records of which publications (post_id) visible to the user (user_id) in his feed.

    Code for adding an entry to the user’s feed with user_id = 1:

    INSERT INTO news_feed (user_id, post_id)
    VALUES (1, 5);  -- 5 - это идентификатор публикации
    
  5. Chat and messenger

    If your social network includes chat and messenger functions, then the database structure for storing messages and chats could be similar to the structure presented above for users and their connections.

    Sample code to create a table messagescontaining messages between users:

    CREATE TABLE messages (
        message_id SERIAL PRIMARY KEY,
        sender_id INT,
        receiver_id INT,
        content TEXT,
        sent_at TIMESTAMP DEFAULT NOW(),
        FOREIGN KEY (sender_id) REFERENCES users (user_id),
        FOREIGN KEY (receiver_id) REFERENCES users (user_id)
    );
    

    This table stores messages (content), sent from the sender (sender_id) to the recipient (receiver_id) indicating the time of dispatch (sent_at).

    Example code for sending a message from a user with sender_id = 1 user with receiver_id =2:

INSERT INTO messages (sender_id, receiver_id, content)
VALUES (1, 2, 'Привет, как дела?');

The actual architecture may include additional tables or collections, depending on the functional requirements and features of your project.

System components

The system components for a social network ensure its functionality.

  1. Authentication and Authorization

    Authentication and authorization are the primary components for ensuring security and managing user access to social network resources:

    • Authentication: This process authenticates users. Users must provide proof of their identity, such as a username and password, to log in:

      from flask import Flask, request, jsonify
      from flask_jwt_extended import create_access_token, JWTManager
      
      app = Flask(__name__)
      app.config['JWT_SECRET_KEY'] = 'your-secret-key'
      jwt = JWTManager(app)
      
      @app.route('/login', methods=['POST'])
      def login():
          username = request.json.get('username')
          password = request.json.get('password')
      
          # Проверка логина и пароля (здесь можно использовать базу данных)
          if username == 'user' and password == 'password':
              access_token = create_access_token(identity=username)
              return jsonify(access_token=access_token), 200
          else:
              return jsonify(message="Неверные учетные данные"), 401
      
      if __name__ == '__main__':
          app.run()
      
    • Authorization: This component defines what actions and resources the user can use after authentication. For example, access to a user’s personal page and editing its data should be allowed only to him.

  2. Newsline and feeds

    News feeds and feeds allow users to see content from other users they follow, as well as their own posts:

    • Preparing the Tape: To create a news feed, you can use content filtering and sorting algorithms to display the most relevant and interesting content.

    • Content Management: Users should be able to create and edit their own content, as well as interact with other users’ content (such as liking and commenting).

    • Filtering and subscriptions: Users can choose who to follow to see content only from certain users or groups.

  3. Chat and messenger

    Chat and messenger functionality allows users to communicate in real time. Key aspects:

    • Private and group chats: The system should support both single chats between users and group chats with multiple participants.

    • Notifications: Users should receive notifications about new messages and chat events, even if they are not active on the site.

    • Message storage: Messages can be stored in a database for later viewing and retrieval.

    Example code for sending a chat message in JavaScript using the library Socket.IO:

    // Сервер
    const io = require('socket.io')(server);
    
    io.on('connection', (socket) => {
        socket.on('message', (data) => {
            // Обработка и сохранение сообщения в базе данных
            io.emit('message', data);  // Отправка сообщения всем подключенным клиентам
        });
    });
    
    // Клиент
    const socket = io.connect('http://example.com');
    
    socket.emit('message', {
        sender: 'user1',
        content: 'Привет, как дела?'
    });
    
  4. Search and filter content

    You can use tools like Elasticsearch to search and filter content. Example code to perform a search query using Elasticsearch in Python using the library Elasticsearch-py:

    from elasticsearch import Elasticsearch
    
    # Подключение к Elasticsearch
    es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
    
    # Пример поискового запроса
    def search_content(query):
        results = es.search(index='posts', body={
            'query': {
                'match': {
                    'content': query
                }
            }
        })
        return results['hits']['hits']
    
    # Пример использования
    search_results = search_content('интересная статья')
    
  5. Notifications and Alerts

    To send notifications and alerts, you can use libraries and services such as Firebase Cloud Messaging (FCM) for push notifications. Example code for sending push notification in Python using library PyFCM:

    from pyfcm import FCMNotification
    
    # Инициализация FCM
    push_service = FCMNotification(api_key="your-api-key")
    
    # Отправка уведомления
    registration_id = "device-registration-id"
    message_title = "Новое уведомление"
    message_body = "У вас новое сообщение в чате."
    result = push_service.notify_single_device(
        registration_id=registration_id,
        message_title=message_title,
        message_body=message_body
    )
    
  6. Analytics and monitoring

    Various tools can be used to collect data about user activity and system performance. Example code for logging events using the library logging:

    import logging
    
    # Конфигурация логирования
    logging.basicConfig(filename="app.log", level=logging.INFO)
    
    # Запись события в лог
    logging.info('Пользователь john_doe выполнил вход в систему.')
    

    You can use tools such as Grafana and Prometheus to analyze logs and monitor performance.

Please note that the code examples above are provided for illustration purposes and should be tailored to your project’s specific requirements and environment. Developing and configuring these components may require additional effort and integration.

Scalability and performance

To ensure high availability and responsiveness of the system, it is necessary to properly consider horizontal scaling, caching and query optimization.

  1. Horizontal scaling

    Horizontal scaling involves distributing the load by adding additional servers or nodes to the system. This allows for increased performance and query processing.

    Sample Python code for creating a distributed system using the library Flask And Redis as a task broker:

    from flask import Flask
    from rq import Queue
    from redis import Redis
    
    app = Flask(__name__)
    redis_conn = Redis()
    
    # Создание очереди задач
    task_queue = Queue(connection=redis_conn)
    
    @app.route('/process', methods=['POST'])
    def process_data():
        data = request.json
        # Отправка задачи на выполнение в очередь
        task = task_queue.enqueue(data_processing_function, data)
        return jsonify({'task_id': task.get_id()}), 202
    
    if __name__ == '__main__':
        app.run()
    

    In this example, we used a task queue (in this case, using the RQ library) to process requests asynchronously and relieve the server.

  2. Caching and query optimization

    Caching is an effective way to reduce database load and speed up data access. Caches can be used at both the application level and the database level.

    Sample code for request caching using Python library cachetools:

    from cachetools import TTLCache
    
    # Создание кэша с временем жизни 60 секунд
    cache = TTLCache(maxsize=100, ttl=60)
    
    def get_data_from_cache(key):
        # Попытка получить данные из кэша
        data = cache.get(key)
        if data is not None:
            return data
        else:
            # Если данных нет в кэше, получаем их из базы данных
            data = fetch_data_from_database(key)
            # Сохранение данных в кэше
            cache[key] = data
            return data
    

    Apart from caching, optimizing database queries also plays an important role in ensuring high performance. This may include indexing tables, optimizing SQL queries, and using databases designed with specific queries in mind.

    It’s also important to use performance monitoring tools to identify and fix problems in real time and implement data-driven improvements.

Security and data protection

User information must be reliably protected from unauthorized access and attacks.

  1. Attack protection

    SQL injection: SQL injections occur when an attacker inserts malicious SQL code into user input to gain access to a database or change data. To prevent SQL injections, use parameterized queries and ORM (Object-Relational Mapping) if possible. Example using ORM SQLAlchemy in Python:

    from sqlalchemy import text
    
    # Плохой способ (подвержен SQL-инъекциям)
    user_input = "'; DROP TABLE users;"
    query = f"SELECT * FROM users WHERE username="{user_input}""
    
    # Хороший способ (использование параметров)
    query = text("SELECT * FROM users WHERE username = :username")
    result = db.session.execute(query, {"username": user_input})
    

    Cross-site scripting (XSS): XSS attacks occur when an attacker injects malicious JavaScript code into web pages that runs in other users’ browsers. To protect against XSS, use output escaping features and properly configure Content Security Policy (CSP) headers.

    // Плохой способ (подвержен XSS)
    const user_input = "<script>alert('Вредоносный код');</script>";
    document.getElementById("output").innerHTML = user_input;
    
    // Хороший способ (использование функции экранирования)
    const user_input = "<script>alert('Вредоносный код');</script>";
    document.getElementById("output").textContent = user_input;
    
  2. Data encryption

    Encryption at rest: To protect data at rest (such as user passwords and sensitive messages), use encryption algorithms. HTTPS (TLS/SSL) provides data security between the client and server.

    An example of using HTTPS using the OpenSSL library in Node.js:

    const https = require('https');
    const fs = require('fs');
    
    const options = {
        key: fs.readFileSync('private-key.pem'),
        cert: fs.readFileSync('public-cert.pem')
    };
    
    const server = https.createServer(options, (req, res) => {
        res.statusCode = 200;
        res.setHeader('Content-Type', 'text/plain');
        res.end('Hello, secure world!\n');
    });
    
    server.listen(443);
    
  3. Authentication and Authorization

    Strong authentication: User passwords must be hashed using strong hash functions. Additional security measures may include two-factor authentication (2FA).

    Example of password hashing in Python using library bcrypt:

    import bcrypt
    
    password = "secure_password"
    hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
    

    Authorization: Ensure that users have only the access rights necessary to complete their tasks. Implement a system of roles and access rights.

  4. Authorized access and audit

    Logging and monitoring: Maintain an event log to track user activity and anomalies. Monitor the system for unauthorized access.

    API protection: If you have an API, use authentication and token issuing mechanisms (such as JWT) to provide secure access to data and functionality.

  5. Updates and patches

    Constantly update and patch your application and its dependencies. Emerging vulnerabilities can be used by attackers to attack.

    Ensuring security on a social network is a continuous and multifaceted process. Be sure to audit and test your application for vulnerabilities, monitor library updates and train your security team

It is always better to prevent threats than to react to them.

Server side development

First of all, make sure you have the required libraries installed. You can install them using pip:

pip install flask flask-pymongo flask-restful Flask-JWT-Extended

Example code for creating the server side:

from flask import Flask, request
from flask_restful import Api, Resource, reqparse
from flask_pymongo import PyMongo
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity

app = Flask(__name__)
api = Api(app)
app.config['MONGO_URI'] = 'mongodb://localhost:27017/social_network'
app.config['JWT_SECRET_KEY'] = 'super-secret-key'
mongo = PyMongo(app)
jwt = JWTManager(app)

# Создание модели пользователя
class User(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username', required=True)
        parser.add_argument('password', required=True)
        args = parser.parse_args()
        
        existing_user = mongo.db.users.find_one({'username': args['username']})
        if existing_user:
            return {'message': 'Пользователь с таким именем уже существует'}, 400
        
        user_id = mongo.db.users.insert({'username': args['username'], 'password': args['password']})
        return {'message': 'Пользователь зарегистрирован', 'user_id': str(user_id)}, 201

# Создание ресурсов API
api.add_resource(User, '/user')

if __name__ == '__main__':
    app.run(debug=True)

Client side development

The client side of a social network is usually implemented using web technologies such as HTML, CSS and JavaScript. Depending on the requirements, you can also use frameworks such as React, Angular or Vue.js.

Example code for a simple web page using HTML and JavaScript:

<!DOCTYPE html>
<html>
<head>
    <title>Простая социальная сеть</title>
</head>
<body>
    <h1>Добро пожаловать в социальную сеть</h1>
    <div id="posts">
        <!-- Здесь будут отображаться посты пользователей -->
    </div>
    <textarea id="post-content" placeholder="Напишите свой пост"></textarea>
    <button onclick="createPost()">Опубликовать</button>

    <script>
        function createPost() {
            const content = document.getElementById('post-content').value;
            // Отправка поста на сервер
            // ...
        }

        // Запрос на сервер для загрузки постов
        // ...
    </script>
</body>
</html>

Testing and Debugging

Testing is an important part of development. You can use testing frameworks such as PyTest for Python or Jest for JavaScript to write unit tests, integration tests, and API tests.

Example of a unit test using PyTest for the server side:

import app  # Импорт вашего приложения

def test_create_user():
    client = app.app.test_client()
    response = client.post('/user', json={'username': 'testuser', 'password': 'testpassword'})
    assert b'Пользователь зарегистрирован' in response.data

Implementation and deployment

After completing development, testing and debugging, you can begin the process of implementing and deploying your application.

An example of deployment on a server using the Docker container management tool:

  1. Create a Dockerfile for your application:

FROM python:3.9

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["python", "app.py"]
  1. Build the Docker image:

docker build -t social-network-app .
  1. Start the container:

docker run -p 5000:5000 social-network-app

Your application will now be available on port 5000 on the server.

Conclusion

Social media development is a complex task and you will definitely need to go deeper into many aspects. But remember that the most important thing is the constant desire to improve and learn.

Remember that every successful project starts with the first step. Confidence, persistence and a desire to improve will help you succeed in this exciting field of development. Good luck!

The article was prepared as part of the launch of the course Enterprise Architect. I would like to recommend you free course lessons that you can register for right now:

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *