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.
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.
- 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
mainbranch. - Cloud Database: Powered by Neon's free permanent PostgreSQL.
- Centralized Auth: Secure endpoints protected by JWT validation.
- API Gateway Pattern: API Service acts as the single entry point for all client requests.
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"
NEON[(Neon PostgreSQL)]
end
Client -- HTTP / Bearer JWT --> API
API -- HTTP --> CONTENT
CONTENT -- HTTP --> DB_SVC
DB_SVC -- SSL Connection --> NEON
The API Service (port 3000) functions as the API Gateway:
- Receives all client requests
- Handles JWT authentication
- Routes requests to internal services
| 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 |
| Category | Technologies Used |
|---|---|
| Backend Core | Node.js, Express.js, TypeScript |
| Architecture | Microservices, API Gateway Pattern |
| Database | PostgreSQL (Neon Free Tier) |
| Security | JWT (JSON Web Tokens), bcrypt |
| DevOps & CI/CD | Docker, GitHub Actions |
| Cloud Provider | Render (Web Services) + Neon (PostgreSQL) |
| Container Registry | Docker Hub |
Before running the project, ensure you have:
- Node.js 18+ installed
- Docker Desktop installed and running
- npm or yarn package manager
- Docker Hub account (for container registry)
- Render account (for web services hosting)
- Neon account (for cloud database)
git clone https://github.com/YorberR/Microservices.git
cd Microservicesnpm installCreate 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- Create a database named
microservices - Run the SQL commands in the Database Schema section below
- Create a project at neon.tech
- Create a new PostgreSQL database
- Run the SQL commands in the Database Schema section below
- Update
.envwith your Neon PostgreSQL connection string - Add
DB_SSL=trueto enable SSL connection
docker-compose up --build# Terminal 1 - PostgreSQL Service
npm run dev:postgres
# Terminal 2 - Main API
npm run dev
# Terminal 3 - Post Service
npm run dev:post
# Terminal 4 - Follow Service
npm run dev:follow
# Terminal 5 - Like Service
npm run dev:like| Endpoint | Method | Description |
|---|---|---|
/api/auth/login |
POST | Login and get JWT token |
/api/auth/verify |
POST | Verify JWT token |
| Endpoint | Method | Description |
|---|---|---|
/api/user |
GET | List all users |
/api/user |
POST | Create new user |
/api/user/:id |
GET | Get user by ID |
/api/user/:id |
PUT | Update user |
/api/user/:id |
DELETE | Delete user |
| Endpoint | Method | Description |
|---|---|---|
/api/posts |
GET | List all posts |
/api/posts |
POST | Create new post |
/api/posts/:uuid |
GET | Get post by UUID |
/api/posts/:uuid |
PUT | Update post |
/api/posts/:uuid |
DELETE | Delete post |
/api/posts/user/:userId |
GET | Get posts by user |
| Endpoint | Method | Description |
|---|---|---|
/api/follows |
POST | Follow a user |
/api/follows/:followerId/:followingId |
DELETE | Unfollow |
/api/follows/followers/:userId |
GET | Get followers |
/api/follows/following/:userId |
GET | Get following |
/api/follows/check/:followerId/:followingId |
GET | Check follow status |
| Endpoint | Method | Description |
|---|---|---|
/api/likes |
POST | Like a post |
/api/likes/:userId/:postId |
DELETE | Unlike |
/api/likes/post/:postId |
GET | Get likes on post |
/api/likes/user/:userId |
GET | Get user likes |
/api/likes/check/:userId/:postId |
GET | Check like status |
/api/likes/count/:postId |
GET | Get like count |
- Username:
user1 - Password:
pass123
-
Login: Send username and password to
/api/auth/loginPOST /api/auth/login { "username": "user1", "password": "pass123" }
-
Get Token: Receive JWT in response
{ "error": false, "status": 200, "body": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } -
Use Token: Include JWT in headers for protected endpoints
Authorization: Bearer <your-jwt-token> -
Authorization Check: Other services verify JWT via
/api/auth/verifyPOST /api/auth/verify { "token": "eyJ...", "action": "create", "resource": "post", "ownerId": 1 }
# Build all services
docker-compose builddocker-compose up -ddocker-compose down- Create a Render account (for web services)
- Create a Neon account (for PostgreSQL)
- Create a Docker Hub account
- Create an Access Token in Docker Hub (if logging in via GitHub)
In your GitHub repository, add these secrets:
DOCKER_USERNAME: Your Docker Hub usernameDOCKER_PASSWORD: Your Docker Hub password or access token
Simply push to the main branch:
git add .
git commit -m "Deploy to production"
git push origin mainGitHub Actions will automatically build and push Docker images to Docker Hub.
After images are pushed to Docker Hub:
-
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
- db-service:
-
Create Neon PostgreSQL:
- Go to neon.tech
- Create a new project
- Note the connection details (host, port, user, password, database)
-
Configure Environment Variables for each service:
DB_HOST: your-postgres-host.neon.tech DB_PORT: 5432 DB_NAME: your_database_name DB_USER: your_username DB_PASSWORD: your_password DB_SSL: true
The deployment is designed to be free:
- Render: 750 hours/month across all web services (free tier)
- Neon: Always free PostgreSQL (no expiration)
- Docker Hub: Free container registry
- Services sleep after 15 minutes of inactivity
Estimated Cost: $0/month for typical portfolio traffic
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
β β βββ swagger.json
β β
β βββ follow-service/ # Follows microservice
β β βββ components/follow/
β β βββ index.ts
β β βββ swagger.json
β β
β βββ like-service/ # Likes microservice
β β βββ components/like/
β β βββ index.ts
β β βββ swagger.json
β β
β βββ postgres-service/ # Database access layer
β β βββ index.ts
β β βββ network.ts
β β βββ swagger.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
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)
);| Command | Description |
|---|---|
npm run dev |
Start API service |
npm run dev:postgres |
Start PostgreSQL service |
npm run dev:post |
Start post service |
npm run dev:follow |
Start follow service |
npm run dev:like |
Start like service |
npm run build |
Compile TypeScript |
| Service | URL |
|---|---|
| API | http://localhost:3000 |
| API Docs | 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 |
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
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 Neon PostgreSQL for a permanent, serverless 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.
This project is licensed under the ISC License - see the LICENSE file for details.
Yorber Rojas
- GitHub: @YorberR
- Built with Express.js and TypeScript
- Deployed on Render
- Database hosted on Neon PostgreSQL
- Containerized with Docker
- Images hosted on Docker Hub