Pham Thanh Huy · Junior Back-end Developer

Threads-inspired social platform

Full-stack project built with a backend-first mindset: clean REST API, JWT + refresh token rotation, Redis/BullMQ background jobs, realtime notifications, AI-assisted moderation, Cloudflare R2 media, Docker deployment and cost-aware infrastructure decisions.

01

Main links for recruiters

Frontend · Backend · Frontend repo · Backend repo

These are the four links I would send to a recruiter first. Start with the frontend demo to see the product, then open the backend docs to understand the API and system design. The two repo links are there for source review.

02

Backend highlights

From my CV

These are the backend parts I want reviewers to notice: a layered API, background workers for heavy work, separate boundaries for realtime/AI/media, and infrastructure choices that keep costs low without making the project unrealistic.

Architecture

Layered REST API

The API is split by domain modules instead of putting business logic inside route handlers. Requests go through middleware, Zod validation, controller mapping, service rules and repository access through Prisma/MySQL.

Express 5TypeScriptPrisma 7Swagger
Async system

Redis + BullMQ workers

Work that does not need to block the request is moved to Redis/BullMQ: email, Bloom filter updates, like sync, grouped notifications, AI evaluation, vector indexing and media jobs.

RedisBullMQWorkersDebounce
Cost control

Self-hosted alternatives

I chose cheaper infrastructure where it made sense: Cloudflare R2 for object storage, self-hosted FFmpeg/HLS instead of a paid encoding service, MySQL full-text/NGram instead of Elasticsearch for social search, and Soketi as a Pusher-compatible realtime option.

Cloudflare R2FFmpegSoketiNginx
03

System snapshot

Backend-focused

Một màn hình để reviewer nắm nhanh scope kỹ thuật trước khi đi vào route hoặc source.

Core features
Posts, comments/replies, reposts, follows, friend requests, chat, realtime notifications, upload, search, AI moderation, reports, admin, daily quest và circles.
Security
JWT access token, refresh token rotation, hashed refresh token in DB, logout blacklist in Redis, email verification, password recovery, Zod validation và rate limiting.
Data
MySQL/MariaDB với Prisma ORM, repository pattern, full-text search, NGram indexing, cursor pagination và transactional domain writes.
Realtime
Pusher-compatible realtime layer, private/presence auth, grouped notifications bằng Redis hash/set/zset và worker sync về DB.
Deploy
Docker image build qua GitHub Actions, push Amazon ECR, deploy EC2 bằng SSH, Nginx reverse proxy, migration chạy sau compose up.
04

Current shared infrastructure

Current setup

This is the current shared-infra setup. The idea is simple: keep the reverse proxy, the app, and the data services separate, so Nginx, Redis and MySQL can be reused without putting every container into one large compose file. I will add the newer infrastructure details later.

Folder layout

Folders are split by runtime responsibility

infa/ contains shared services such as Redis and MySQL. They are kept outside the app folder so the app can be redeployed without touching database/cache state. proxy/ contains Nginx, domain routing and the public entrypoint. threads/ contains the Threads app itself: API container, workers, realtime service and app-specific compose/env files.

infa: redis + mysqlproxy: nginxthreads: app
Network layout

Networks follow how containers talk to each other

proxy-app lets Nginx in proxy/ reach the app in threads/ and forward traffic to the API/realtime service. app-net connects the app to Redis and MySQL in infa/; it is marked external: true because multiple compose projects attach to the same pre-created network. Containers that are only used inside Threads stay on threads-network.

proxy-appapp-net external truethreads-network
InternetUsers reach the app through an HTTPS domain. Requests do not go straight to the app container.
proxy/ nginxNginx handles the domain and forwards traffic to Threads through proxy-app.
threads/ appThe API handles HTTP, workers process background jobs, and realtime services handle chat/notifications.
infa/ mysqlMySQL stays in shared infra and is reached through app-net external.
infa/ redisRedis is used for cache, queues, Bloom filter and notification debounce through app-net external.

Note: this repo still has older compose files such as docker-compose.yml and docker-compose.provider.yaml. This section describes the shared-infra layout I want to show in the portfolio: shared infra in infa/, proxy in proxy/, and the app in threads/. The newer infra section can later add domain routing, SSL, backup, monitoring and rollout details.

05

Plan, QA và tài liệu phụ

Đưa xuống cuối trang

Các link này vẫn hữu ích khi reviewer muốn đào sâu, nhưng không đặt trước 4 card tuyển dụng.