Back to blog

Build a Video Streaming Platform: Series Overview

javaspring-bootreactnextjsvideo-streaming
Build a Video Streaming Platform: Series Overview

Every developer has watched a course on Udemy, Coursera, or Pluralsight. You click play, the video streams smoothly, you pick up where you left off, and your subscription renews automatically. Simple experience, right?

Behind that simplicity is a surprisingly deep engineering challenge. Video transcoding, adaptive bitrate streaming, secure content delivery, subscription billing, progress tracking, admin dashboards — a video platform touches backend, frontend, DevOps, and payment infrastructure all at once.

That's what makes it the perfect project to build from scratch. In this 15-post series, we'll go from an empty directory to a production-deployed, self-hosted video course platform with subscriptions, using Spring Boot, Next.js, FFmpeg, PostgreSQL, Redis, and Stripe.

Why Build a Video Streaming Platform?

A video platform is one of the most complete full-stack projects you can build. It covers a wide range of real-world challenges:

Video processing — transcoding with FFmpeg, HLS adaptive bitrate streaming
Secure content delivery — signed URLs, Nginx token validation, preventing downloads
Subscription billing — Stripe Checkout, webhooks, subscription lifecycle management
Authentication — JWT tokens, OAuth2 social login (Google, GitHub)
Database design — courses, sections, lessons, subscriptions, progress tracking
Admin dashboard — content management, analytics, user management
Frontend development — custom video player, course catalog, responsive UI
DevOps — Docker Compose, Nginx reverse proxy, VPS deployment
Performance — Redis caching, async processing, CDN-ready architecture

Unlike toy projects, a video platform has real production concerns: How do you stream video without buffering? How do you prevent unauthorized access to paid content? How do you handle a failed payment mid-subscription? How do you transcode a 2GB upload without blocking your server?


What We're Building

By the end of this series, you'll have a fully functional video course platform with these features:

Core Features

  • Video upload & transcoding — upload MP4 files, auto-transcode to HLS with multiple quality levels (360p, 720p)
  • Adaptive streaming — video player automatically switches quality based on network speed
  • Course management — organize content into courses → sections → lessons
  • Subscription billing — Stripe-powered monthly/yearly plans with automatic renewal
  • Progress tracking — resume videos from where you left off, track course completion

User Features

  • Email + social login — register with email/password or sign in with Google/GitHub
  • Course catalog — browse, filter, and preview courses before subscribing
  • Free previews — selected lessons available without subscription
  • Video player — quality selector, playback speed (0.5x–2x), fullscreen, keyboard shortcuts
  • Account management — view subscription status, manage billing via Stripe Portal

Admin Features

  • Content dashboard — create/edit/publish courses with drag-and-drop lesson ordering
  • Video management — upload videos, monitor transcoding progress, re-upload failed ones
  • User management — view subscribers, grant manual access, search users
  • Analytics — revenue charts, popular lessons, completion rates, subscriber growth

Tech Stack

Here's every technology we'll use and why:

LayerTechnologyWhy
BackendSpring Boot 3 (Java 17+)Production-grade framework with built-in security, async processing, and excellent Stripe/OAuth2 integration
FrontendNext.js 15 (React 19)SSR for SEO on public pages, CSR for app/admin pages, App Router for modern patterns
DatabasePostgreSQL 17ACID transactions, relational model perfect for courses/users/subscriptions, powerful indexing
CacheRedis 7JWT refresh token store, transcoding progress tracking, course catalog caching
VideoFFmpeg 6Industry-standard transcoder, HLS output with adaptive bitrate, thumbnail generation
StreamingNginx + HLSNginx serves video segments directly from disk — fast, zero JVM overhead
PaymentsStripeHosted Checkout (PCI-compliant), Customer Portal, webhook-driven subscription lifecycle
AuthSpring Security + JWTAccess/refresh token pattern, OAuth2 client for Google/GitHub
UI Componentsshadcn/ui + Tailwind CSSBeautiful, accessible components built on Radix UI, utility-first styling
DeploymentDocker ComposeSingle-command deployment of all 5 services (API, web, Postgres, Redis, Nginx)

System Architecture

Here's a high-level view of the system we'll build:

Key architectural decision: Nginx serves HLS video segments directly from disk. The Spring Boot API only generates signed URLs and validates subscriptions — it never touches the actual video bytes. This keeps the JVM free for API requests while Nginx handles high-throughput file serving.

Request Flow: Watching a Video

Request Flow: Uploading & Transcoding a Video


Database Schema Preview

Here's the schema we'll design and iterate on throughout the series:

Key design decisions we'll explore:

  • Why video_path instead of storing video bytes? — videos live on disk as HLS segments, the database just stores the path
  • Why is_free_preview on lessons? — allows selected lessons to be streamed without a subscription, driving conversion
  • Why separate lesson_progress and course_enrollments? — granular per-lesson tracking vs. high-level course completion percentage
  • Why stripe_subscription_id on subscriptions? — Stripe is the source of truth; we mirror state locally via webhooks

Complete Series Roadmap

Post #1: Series Overview & ArchitectureYou are here

  • Why build a video platform
  • Tech stack decisions and trade-offs
  • System architecture and data flow
  • Database schema preview

Phase 1: Project Setup

Post #2: Project Setup (Spring Boot + Next.js + Docker Compose)

Topics:

  • Spring Boot project scaffolding with Spring Initializr
  • Next.js project with App Router, TypeScript, Tailwind CSS
  • Docker Compose for development (API, web, PostgreSQL, Redis)
  • Project structure and module organization
  • Development workflow with hot reload
  • Environment configuration and profiles

Learning Outcomes:
✅ Set up a Spring Boot + Next.js monorepo from scratch
✅ Configure Docker Compose for multi-service development
✅ Establish project structure for a scalable full-stack app
✅ Run the complete development stack with one command


Phase 2: Authentication

Post #3: Authentication (JWT + OAuth2 Social Login)

Topics:

  • Spring Security configuration for JWT
  • Access token (15 min) + refresh token (7 days) pattern
  • Email/password registration and login
  • Google and GitHub OAuth2 social login
  • BCrypt password hashing
  • Next.js auth context and protected routes
  • Token refresh interceptor with Axios

Learning Outcomes:
✅ Implement JWT authentication with Spring Security
✅ Add Google and GitHub OAuth2 social login
✅ Build a secure token refresh flow
✅ Protect frontend routes based on auth state


Phase 3: Course Data Model

Post #4: Course & Lesson Data Model (JPA + Flyway Migrations)

Topics:

  • JPA entity design (Course, Section, Lesson relationships)
  • Flyway migration scripts for schema versioning
  • Admin CRUD API for courses, sections, and lessons
  • Slug generation and uniqueness enforcement
  • Sort order management for drag-and-drop reordering
  • DTO mapping with MapStruct

Learning Outcomes:
✅ Design JPA entities with proper relationships
✅ Manage database schema changes with Flyway
✅ Build admin CRUD endpoints with validation
✅ Handle sort ordering for nested content


Phase 4: Admin Dashboard

Post #5: Admin Dashboard (React + shadcn/ui + Drag-and-Drop)

Topics:

  • Next.js admin layout with sidebar navigation
  • Course editor form with react-hook-form and Zod validation
  • Section and lesson management UI
  • Drag-and-drop reordering with @dnd-kit
  • Course publishing workflow (DRAFT → PUBLISHED → ARCHIVED)
  • Admin route protection with role checking

Learning Outcomes:
✅ Build a complete admin dashboard with shadcn/ui
✅ Create forms with client-side validation
✅ Implement drag-and-drop content reordering
✅ Handle publishing workflows with status transitions


Phase 5: Video Upload

Post #6: Video Upload & Storage

Topics:

  • Multipart file upload with Spring Boot (up to 2GB)
  • File validation (format, size, MIME type)
  • Storage layout design on VPS disk
  • Upload progress tracking
  • Admin UI for video upload with progress bar
  • Handling upload failures and retry

Learning Outcomes:
✅ Handle large file uploads with Spring Boot
✅ Validate and store video files securely
✅ Design a disk storage layout for video content
✅ Build an upload UI with real-time progress


Phase 6: Video Transcoding

Post #7: Video Transcoding Pipeline (FFmpeg + HLS)

Topics:

  • FFmpeg basics: codecs, containers, bitrates
  • HLS (HTTP Live Streaming) format explained
  • Transcoding to multiple quality levels (360p + 720p)
  • Async processing with Spring @Async and ThreadPoolTaskExecutor
  • Progress tracking via Redis (parsing FFmpeg stderr)
  • Thumbnail generation with ffprobe
  • Error handling and retry for failed transcodes

Learning Outcomes:
✅ Understand HLS streaming and adaptive bitrate
✅ Build an FFmpeg transcoding pipeline in Java
✅ Process videos asynchronously without blocking the API
✅ Track transcoding progress in real-time


Phase 7: Secure Streaming

Post #8: Secure Video Streaming (Nginx + Signed URLs)

Topics:

  • Nginx configuration for serving HLS files
  • Nginx secure_link module for token validation
  • Signed URL generation in Spring Boot (MD5 + expiry)
  • CORS configuration for video requests
  • Cache headers for video segments
  • Preventing direct video download

Learning Outcomes:
✅ Configure Nginx to serve HLS video segments
✅ Secure video content with signed URLs
✅ Validate streaming tokens at the Nginx layer
✅ Prevent unauthorized access to paid content


Phase 8: Video Player

Post #9: Video Player & Progress Tracking (hls.js + React)

Topics:

  • HLS playback with hls.js in the browser
  • Custom React video player component
  • Quality selector, playback speed, fullscreen controls
  • Resume from last position on page load
  • Debounced progress saving (every 30 seconds)
  • navigator.sendBeacon for progress on page unload
  • Auto-complete lessons at >90% watched
  • Course enrollment and progress percentage

Learning Outcomes:
✅ Build a custom video player with hls.js
✅ Track and persist watch progress per lesson
✅ Resume playback from last watched position
✅ Calculate course completion percentage


Phase 9: Stripe Integration

Post #10: Stripe Subscription Integration

Topics:

  • Stripe Checkout Session for payment collection
  • Webhook handler for subscription events
  • Subscription lifecycle (active → past_due → canceled → expired)
  • Stripe Customer Portal for self-service management
  • Access gating middleware (subscription check)
  • Grace period handling for failed payments
  • Testing with Stripe CLI and test mode

Learning Outcomes:
✅ Integrate Stripe Checkout for subscription payments
✅ Handle Stripe webhooks for subscription lifecycle
✅ Gate content access based on subscription status
✅ Enable self-service subscription management


Phase 10: Course Catalog

Post #11: Public Course Catalog & SEO

Topics:

  • Server-rendered course catalog with Next.js SSR
  • Course detail page with curriculum outline
  • Free preview lesson playback for non-subscribers
  • generateMetadata() for Open Graph tags
  • JSON-LD structured data (Course schema)
  • Sitemap and robots.txt generation
  • Responsive catalog grid with filtering

Learning Outcomes:
✅ Build SEO-optimized public pages with Next.js SSR
✅ Implement free preview lessons to drive conversions
✅ Add structured data for search engine visibility
✅ Create a responsive course catalog with filtering


Phase 11: Analytics

Post #12: Admin Analytics & User Management

Topics:

  • Dashboard metrics (subscribers, revenue, content stats)
  • Revenue charts with Recharts
  • Popular lessons and completion rate analytics
  • User management (list, search, filter by subscription)
  • Manual access grants for testing and promotions
  • Data tables with @tanstack/react-table

Learning Outcomes:
✅ Build admin analytics with aggregation queries
✅ Visualize data with Recharts charts
✅ Create user management with search and actions
✅ Handle manual subscription overrides


Phase 12: Security

Post #13: Security & Performance Hardening

Topics:

  • Rate limiting on auth and API endpoints
  • HLS AES-128 encryption with FFmpeg
  • CORS, CSP, and security headers
  • Redis caching for course listings (5-min TTL)
  • Next.js ISR for course pages
  • Email notifications (welcome, subscription, expiry reminder)
  • Spring Boot Actuator health checks

Learning Outcomes:
✅ Harden the platform against common attacks
✅ Encrypt video segments with AES-128
✅ Improve performance with caching and ISR
✅ Add email notifications for key user events


Phase 13: Testing

Post #14: Testing Strategy (Unit, Integration, E2E)

Topics:

  • Unit testing with JUnit 5 + Mockito (services, utilities)
  • Spring Boot test slices (@WebMvcTest, @DataJpaTest)
  • Integration testing with Testcontainers (PostgreSQL, Redis)
  • Testing Stripe webhooks with mock events
  • Frontend testing with Playwright
  • Test coverage and CI integration

Learning Outcomes:
✅ Write unit tests for Spring Boot services
✅ Build integration tests with Testcontainers
✅ Test payment webhooks without real charges
✅ Set up end-to-end tests with Playwright


Phase 14: Deployment

Post #15: Deployment & Production (Docker + VPS)

Topics:

  • Multi-stage Docker builds for Spring Boot and Next.js
  • Production Docker Compose (5 services: API, web, Postgres, Redis, Nginx)
  • Nginx SSL with Let's Encrypt and certbot
  • Flyway migrations in production
  • Deployment script (rsync-based)
  • Database backup strategy (pg_dump + off-site storage)
  • Monitoring with Spring Boot Actuator
  • VPS sizing and cost estimation

Learning Outcomes:
✅ Containerize the full application for production
✅ Configure Nginx with SSL termination
✅ Deploy to a VPS with a single script
✅ Set up backups and monitoring for production


Architecture Decisions Explained

Before we start coding, let's understand a few key decisions:

Why Spring Boot over Express or FastAPI?

Spring Boot is the most widely used enterprise Java framework. For a video platform that handles file uploads, async transcoding, and payment webhooks, Spring Boot gives us:

  • Built-in async processing@Async with thread pool executors, perfect for video transcoding
  • Spring Security — OAuth2 client, JWT validation, role-based access control out of the box
  • Robust file handling — multipart uploads up to 2GB with streaming support
  • Stripe SDK — first-class Java SDK with type-safe webhook handling
  • Production-proven — battle-tested for exactly this kind of backend workload

Why Self-Hosted Video over YouTube/Vimeo/Bunny.net?

Third-party video hosts are easier to set up but come with trade-offs:

  • Cost at scale — Bunny.net charges per GB of bandwidth; self-hosted has fixed VPS cost
  • Control — you own the content, the player, and the user experience
  • Learning — the whole point is to learn how video streaming works end-to-end
  • No vendor lock-in — migrate to any infrastructure without re-uploading everything

For a real business, you'd likely start with a third-party host and move to self-hosted as you scale. We're going self-hosted because this is a learning project.

Why HLS over DASH or Progressive Download?

HLS (HTTP Live Streaming) is the dominant streaming protocol:

  • Adaptive bitrate — player switches quality automatically based on network speed
  • Nginx-native — HLS is just HTTP file serving, no special media server needed
  • Universal support — works in all browsers via hls.js, native on Safari/iOS
  • CDN-friendly — static .ts segment files cache perfectly on any CDN

DASH (Dynamic Adaptive Streaming over HTTP) is technically similar but has less browser support. Progressive download (single MP4 file) can't adapt to network conditions and wastes bandwidth.

Why Stripe Checkout over Custom Payment Forms?

Stripe Checkout is a hosted payment page that handles:

  • PCI compliance — card numbers never touch your server
  • 3D Secure / SCA — strong customer authentication built-in
  • Tax calculation — automatic tax handling in supported regions
  • Mobile-optimized — responsive payment form with Apple Pay / Google Pay
  • Subscription management — Customer Portal for plan changes and cancellation

Building a custom payment form means handling PCI compliance yourself. For a small platform, Stripe Checkout eliminates an entire category of security concerns.


Learning Paths

Choose the path that matches your goals:

Path 1: Backend Developer (Posts 1–10)

Time: 5–6 weeks, 1–2 hours daily
Focus: API design, video pipeline, payments, auth

Skip the frontend-heavy posts (5, 9, 11) and use curl or Postman to test your APIs. This path covers the core backend engineering — video transcoding, secure streaming, and Stripe integration.

Path 2: Full-Stack Developer (All 15 Posts)

Time: 8–9 weeks, 1–2 hours daily
Focus: End-to-end platform development

Follow every post in order. You'll build the complete platform from Spring Boot API to Next.js frontend to VPS deployment.

Path 3: DevOps Focus (Posts 2, 7–8, 14–15)

Time: 2–3 weeks, 1–2 hours daily
Focus: Docker, Nginx, video infrastructure, deployment

Focus on the infrastructure side — Docker Compose setup, FFmpeg pipeline, Nginx streaming config, testing, and production deployment.

Path 4: Payments & SaaS Focus (Posts 1–3, 10–12)

Time: 3–4 weeks, 1–2 hours daily
Focus: Auth, Stripe subscriptions, analytics

Build the auth system, integrate Stripe, and add analytics. This path covers the business logic of a SaaS platform — perfect if you're planning to build a subscription product.


Prerequisites

Before starting this series, you should be comfortable with:

  • Java 17+ — classes, interfaces, annotations, lambdas, streams
  • Spring Boot basics — controllers, services, dependency injection, application properties
  • React fundamentals — components, hooks, state management, API calls
  • SQL basics — SELECT, INSERT, JOIN, indexes
  • Docker basics — running containers, Dockerfiles (we'll cover Docker Compose in detail)
  • Git — commits, branches, basic workflow

New to Spring Boot? Check out the Spring Boot Learning Roadmap and Getting Started with Spring Boot first.

New to React/Next.js? See the React Fundamentals post.


Video Platform vs Other Projects

Why is a video platform better than a todo app or an e-commerce site for learning?

AspectTodo AppE-CommerceVideo Platform
File handlingNoneImage uploadsMulti-GB video uploads + transcoding
StreamingNoneNoneHLS adaptive bitrate streaming
Async processingNoneOrder emailsVideo transcoding pipeline
PaymentsNoneOne-time checkoutRecurring subscriptions + webhooks
Content securityNoneNoneSigned URLs + token validation
Auth complexityBasicMediumJWT + OAuth2 + subscription gating
InfrastructureSingle serverApp + DBApp + DB + Redis + Nginx + FFmpeg
System designTrivialMediumReal production-grade architecture

A video platform is complex enough to teach enterprise engineering skills but focused enough to build in a few months. It's also directly applicable — if you ever want to launch your own course platform, you'll have the foundation ready.


What's Next?

In Post #2, we'll scaffold our Spring Boot API and Next.js frontend from scratch, wire them together with Docker Compose (PostgreSQL, Redis, and all), and establish the project structure that will carry us through the entire series. By the end of Post #2, you'll have a running development stack with hot reload on both backend and frontend.

Let's build something real.

Series: Build a Video Streaming Platform
Next: Phase 1: Project Setup

📬 Subscribe to Newsletter

Get the latest blog posts delivered to your inbox every week. No spam, unsubscribe anytime.

We respect your privacy. Unsubscribe at any time.

💬 Comments

Sign in to leave a comment

We'll never post without your permission.