Skip to content

Repository files navigation

🌐 Social Network Microservices API

A robust, scalable RESTful API built with a microservices architecture for a social networking platform. This project demonstrates advanced skills in distributed systems, Serverless deployment, and CI/CD pipelines.

Architecture: Microservices Deployment: Render Database: Render PostgreSQL CI/CD: GitHub Actions Container Registry: Docker Hub Version: 1.1.0 API Docs: Scalar


πŸ“‹ Overview

This system implements the core backend logic for a social network. Instead of a traditional monolith, the application is divided into 3 containerized services that communicate via HTTP. It features centralized JWT authentication and a fully automated deployment pipeline to Docker Hub.

✨ Key Features

  • Distributed Architecture: Services for Users, Posts, Follows, and Likes.
  • Multi-Process Container: Multiple Node.js processes running in a single container with shell script.
  • Automated CI/CD: GitHub Actions workflow automatically builds Docker images and pushes to Docker Hub on every push to the main branch.
  • Cloud Database: Powered by Render's managed PostgreSQL (free tier).
  • Centralized Auth: Secure endpoints protected by JWT validation.
  • API Gateway Pattern: API Service acts as the single entry point for all client requests.

πŸ—οΈ System Architecture

The application uses an API Gateway pattern where the API Service is the single entry point, with a shell script managing multiple processes within a container.

graph TD
    Client([Client / App / Postman])
    
    subgraph "Render Cloud"
        API[API Gateway\n:3000]
        CONTENT[Content Service\n:3001,3003,3004]
        DB_SVC[DB Service\n:3002]
    end
    
    subgraph "External"
        PG[(Render PostgreSQL)]
    end

    Client -- HTTP / Bearer JWT --> API
    
    API -- HTTP --> CONTENT
    CONTENT -- HTTP --> DB_SVC
    
    DB_SVC -- SSL Connection --> PG
Loading

API Gateway Pattern

The API Service (port 3000) functions as the API Gateway:

  • Receives all client requests
  • Handles JWT authentication
  • Routes requests to internal services

Service Distribution

Service Container Ports Description
api-service Docker 3000 Auth + Users + Routing
content-service Docker (shell script) 3001, 3003, 3004 Posts + Follows + Likes
db-service Docker 3002 Database access layer

πŸš€ Tech Stack

Category Technologies Used
Backend Core Node.js, Express.js, TypeScript
Architecture Microservices, API Gateway Pattern
Database PostgreSQL (Render Managed - Free Tier)
Security JWT (JSON Web Tokens), bcrypt
API Docs OpenAPI 3.0 rendered with Scalar (@scalar/express-api-reference)
DevOps & CI/CD Docker, GitHub Actions
Cloud Provider Render (Web Services + Managed PostgreSQL)
Container Registry Docker Hub

πŸ“¦ Prerequisites

Before running the project, ensure you have:

  • Node.js 22+ installed
  • Docker Desktop installed and running
  • pnpm package manager
  • Docker Hub account (for container registry)
  • Render account (for web services hosting and managed PostgreSQL)

πŸš€ Quick Start

1. Clone the Repository

git clone https://github.com/YorberR/Microservices.git
cd Microservices

2. Install Dependencies

pnpm install

3. Configure Environment Variables

Create a .env file in the root directory:

API_PORT=3000
JWT_SECRET=your-secret-key

DB_HOST=localhost
DB_PORT=5432
DB_NAME=microservices
DB_USER=postgres
DB_PASSWORD=postgres

POST_SERVICE_PORT=3001
FOLLOW_SERVICE_PORT=3003
LIKE_SERVICE_PORT=3004
PG_SERVICE_PORT=3002

4. Set Up Database

Option A: Local PostgreSQL

  1. Create a database named microservices
  2. Run the SQL commands in the Database Schema section below

Option B: Render Managed PostgreSQL (Recommended for Cloud)

  1. Create a PostgreSQL instance in the Render Dashboard
  2. Copy the connection details (Host, Port, Database, User, Password) from the Render database dashboard
  3. Run the SQL commands in the Database Schema section below
  4. Update .env with your Render PostgreSQL connection details
  5. Add DB_SSL=true if your connection requires SSL

5. Run Locally

With Docker (Recommended)

docker-compose up --build

Without Docker (Individual Services)

# Terminal 1 - PostgreSQL Service
pnpm run dev:postgres

# Terminal 2 - Main API
pnpm run dev

# Terminal 3 - Post Service
pnpm run dev:post

# Terminal 4 - Follow Service
pnpm run dev:follow

# Terminal 5 - Like Service
pnpm run dev:like

πŸ“š API Endpoints

Base URL: http://localhost:3000/api

All endpoints are RESTful and require JWT authentication unless otherwise noted.

Authentication

Endpoint Method Description
/api/auth/login POST Login with username/password, returns JWT token
/api/auth/verify POST Verify JWT token and permissions

Login Example (cURL)

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"user1","password":"pass123"}'

Login Response

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 86400
}

Users

Endpoint Method Description Auth
/api/user GET List all users Optional
/api/user POST Create new user Optional
/api/user/:id GET Get user by ID Optional
/api/user/:id PUT Update user (own record only) Optional
/api/user/:id DELETE Delete user (own record only) Optional
/api/user/query POST Query users Required
/api/user/aggregate POST Aggregate user data Required

Create User Example (cURL)

curl -X POST http://localhost:3000/api/user \
  -H "Content-Type: application/json" \
  -d '{"name":"new_user","password":"secure_password123","email":"newuser@example.com"}'

Get Users Example (cURL with Token)

curl -X GET http://localhost:3000/api/user \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Posts

Endpoint Method Description Auth
/api/posts GET List all posts Required
/api/posts POST Create new post Required
/api/posts/:uuid GET Get post by UUID Required
/api/posts/:uuid PUT Update post (owner only) Required
/api/posts/:uuid DELETE Delete post (owner only) Required
/api/posts/user/:userId GET Get posts by user Required

Create Post Example (cURL with Token)

curl -X POST http://localhost:3000/api/posts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{"user_id":1,"content":"Hello world! This is my first post."}'

List Posts Example (cURL with Token)

curl -X GET http://localhost:3000/api/posts \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Follows

Endpoint Method Description Auth
/api/follows POST Follow a user Required
/api/follows/:followerId/:followingId DELETE Unfollow a user Required
/api/follows/followers/:userId GET Get followers Required
/api/follows/following/:userId GET Get following Required
/api/follows/check/:followerId/:followingId GET Check follow status Required

Follow User Example (cURL with Token)

curl -X POST http://localhost:3000/api/follows \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{"follower_id":1,"following_id":2}'

Unfollow Example (cURL with Token)

curl -X DELETE http://localhost:3000/api/follows/1/2 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Likes

Endpoint Method Description Auth
/api/likes POST Like a post Required
/api/likes/:userId/:postId DELETE Unlike a post Required
/api/likes/post/:postId GET Get likes on a post Required
/api/likes/user/:userId GET Get user likes Required
/api/likes/check/:userId/:postId GET Check like status Required
/api/likes/count/:postId GET Get like count Required

Like a Post Example (cURL with Token)

curl -X POST http://localhost:3000/api/likes \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{"user_id":1,"post_id":1}'

Like Count Example (cURL with Token)

curl -X GET http://localhost:3000/api/likes/count/1 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

πŸ” Authentication

Test Credentials

  • Username: user1
  • Password: pass123

Authentication Flow

  1. Login: Send username and password to /api/auth/login

    POST /api/auth/login
    {
      "username": "user1",
      "password": "pass123"
    }

    Receive JWT token in response

  2. Get Token: The JWT is returned in the response body

    {
      "error": false,
      "status": 200,
      "body": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
  3. Use Token: Include JWT in the Authorization header for all protected endpoints

    Authorization: Bearer <your-jwt-token>
    
  4. Verify Token: Optional - Validate token via /api/auth/verify

    POST /api/auth/verify
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "action": "create",
      "resource": "post",
      "ownerId": 1
    }

πŸ“– Interactive API Documentation

  • Scalar UI: Visit http://localhost:3000/api-docs to explore the API interactively
  • All endpoints are documented with request/response examples, authentication requirements, and error codes

🐳 Docker

Build Docker Images

# Build all services
docker-compose build

Run with Docker Compose

docker-compose up -d

Stop Services

docker-compose down

☁️ Deployment (Render + Docker Hub + Render PostgreSQL)

Prerequisites

  1. Create a Render account (for web services)
  2. Create a Render PostgreSQL instance (for PostgreSQL)
  3. Create a Docker Hub account
  4. Create an Access Token in Docker Hub (if logging in via GitHub)

Configure GitHub Secrets

In your GitHub repository, add these secrets:

  • DOCKER_USERNAME: Your Docker Hub username
  • DOCKER_PASSWORD: Your Docker Hub password or access token

Deploy

Simply push to the main branch:

git add .
git commit -m "Deploy to production"
git push origin main

GitHub Actions will automatically build and push Docker images to Docker Hub.

Render Setup

After images are pushed to Docker Hub:

  1. Create Web Services in Render:

    • db-service: docker.io/your-username/db-service:latest, port 3002
    • api-service: docker.io/your-username/api-service:latest, port 3000
    • content-service: docker.io/your-username/content-service:latest, port 3001
  2. Create Render PostgreSQL:

    • Go to the Render Dashboard
    • Create a new PostgreSQL instance
    • Note the connection details (host, port, user, password, database)
  3. Configure Environment Variables for each service:

    DB_HOST: your-render-postgres-host
    DB_PORT: 5432
    DB_NAME: your_database_name
    DB_USER: your_username
    DB_PASSWORD: your_password
    DB_SSL: true
    

Cost Optimization

The deployment is designed to be free:

  • Render: 750 hours/month across all web services (free tier)
  • Render PostgreSQL: Managed PostgreSQL free tier available
  • Docker Hub: Free container registry
  • Services sleep after 15 minutes of inactivity

Estimated Cost: $0/month for typical portfolio traffic


πŸ“‚ Project Structure

microservices/
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── deploy.yml              # CI/CD for Docker Hub
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ api/                       # Main API service
β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/              # Authentication
β”‚   β”‚   β”‚   └── user/              # User management
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   └── Dockerfile             # β†’ api-service
β”‚   β”‚
β”‚   β”œβ”€β”€ content-service/           # Multi-service container (Post + Follow + Like)
β”‚   β”‚   β”œβ”€β”€ Dockerfile             # β†’ content-service
β”‚   β”‚   β”œβ”€β”€ start.sh              # Shell script to start all services
β”‚   β”‚   └── (references post/follow/like services)
β”‚   β”‚
β”‚   β”œβ”€β”€ post-service/              # Posts microservice
β”‚   β”‚   β”œβ”€β”€ components/post/
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   └── scalar.json
β”‚   β”‚
β”‚   β”œβ”€β”€ follow-service/             # Follows microservice
β”‚   β”‚   β”œβ”€β”€ components/follow/
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   └── scalar.json
β”‚   β”‚
β”‚   β”œβ”€β”€ like-service/              # Likes microservice
β”‚   β”‚   β”œβ”€β”€ components/like/
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   └── scalar.json
β”‚   β”‚
β”‚   β”œβ”€β”€ postgres-service/          # Database access layer
β”‚   β”‚   β”œβ”€β”€ index.ts
β”‚   β”‚   β”œβ”€β”€ network.ts
β”‚   β”‚   β”œβ”€β”€ scalar.json
β”‚   β”‚   └── Dockerfile             # β†’ db-service
β”‚   β”‚
β”‚   β”œβ”€β”€ store/                     # Database clients
β”‚   β”‚   β”œβ”€β”€ postgres.ts            # PostgreSQL client
β”‚   β”‚   └── remote.ts              # HTTP client
β”‚   β”‚
β”‚   β”œβ”€β”€ auth/                      # JWT utilities
β”‚   β”œβ”€β”€ network/                   # Response helpers
β”‚   β”œβ”€β”€ utils/                     # Error handling
β”‚   └── config.ts                  # Configuration
β”‚
β”œβ”€β”€ .dockerignore
β”œβ”€β”€ .env                           # Environment variables
β”œβ”€β”€ docker-compose.yml             # Docker Compose (local)
β”œβ”€β”€ package.json
└── tsconfig.json

πŸ—„οΈ Database Schema

Create these tables in your PostgreSQL database:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    uuid VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    uuid VARCHAR(50) UNIQUE NOT NULL,
    user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE follows (
    id SERIAL PRIMARY KEY,
    follower_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    following_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(follower_id, following_id)
);

CREATE TABLE likes (
    id SERIAL PRIMARY KEY,
    user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    post_id INTEGER NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(user_id, post_id)
);

πŸ“ Available Scripts

Command Description
pnpm run dev Start API service
pnpm run dev:postgres Start PostgreSQL service
pnpm run dev:post Start post service
pnpm run dev:follow Start follow service
pnpm run dev:like Start like service
pnpm run build Compile TypeScript

πŸ”— Service URLs (Local Development)

Service URL
API http://localhost:3000
API Docs (Scalar) http://localhost:3000/api-docs
Post Service http://localhost:3001
Follow Service http://localhost:3003
Like Service http://localhost:3004
Postgres Service http://localhost:3002

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ’‘ Inspiration & Architectural Evolution

This project was originally inspired by the architectural concepts taught in a microservices course at [Platzi]. However, to challenge myself and align the system with modern enterprise standards, I completely re-architected the original baseline.

Key improvements and deviations from the original course include:

  • Language Upgrade: Migrated the entire codebase from plain JavaScript to strict TypeScript to ensure type safety, better developer experience, and maintainability.
  • Database Modernization: Replaced the traditional local MySQL setup with Render PostgreSQL for a managed cloud database.
  • Multi-Process Container: Implemented a shell script approach to run multiple Node.js processes within a single container, optimizing for free tier deployment.
  • Container Registry: Integrated Docker Hub for hosting container images with automated CI/CD via GitHub Actions.
  • Cloud Deployment: Migrated from local deployments to Render for production-ready web services.
  • API Gateway Pattern: Implemented the API Service as the single entry point for all client requests, handling authentication and routing.

πŸ“„ License

This project is licensed under the ISC License - see the LICENSE file for details.


πŸ‘€ Author

Yorber Rojas


πŸ™ Acknowledgments

  • Built with Express.js and TypeScript
  • Deployed on Render
  • Database hosted on Render PostgreSQL
  • Containerized with Docker
  • Images hosted on Docker Hub

About

Cloud-native social network API built with a decoupled Microservices architecture (Node.js/TypeScript). Features JWT auth, automated CI/CD via GitHub Actions to Docker Hub, and deployed on Render.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages