In this article, I'll walk through the architecture of TrendVidStream, a video streaming platform that aggregates trending content from 8 countries: US, UK, Switzerland, Denmark, UAE, Belgium, Czech Republic, and Finland.
Architecture Overview
The platform runs on PHP 8.3 with SQLite as the sole database, deployed across 4 LiteSpeed servers. Each server handles different global regions with its own cron schedule.
┌─────────────────────────────────────────────────────────────┐
│ TrendVidStream Architecture │
├─────────────────────────────────────────────────────────────┤
│ YouTube API ──> PHP Fetcher ──> SQLite DB │
│ │ │ │ │
│ 8 Regions Normalize & 3-Tier Cache │
│ per cron Score ├─ LiteSpeed │
│ ├─ PHP File │
│ └─ PHP Data │
└─────────────────────────────────────────────────────────────┘
Data Model
The core data model is simple. Videos have an ID, title, description, region, category, and metadata. SQLite stores everything:
<?php
class Database
{
private PDO $pdo;
public function __construct(string $dbPath)
{
$this->pdo = new PDO("sqlite:$dbPath");
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('PRAGMA journal_mode=WAL');
$this->pdo->exec('PRAGMA synchronous=NORMAL');
}
public function upsertVideo(array $video): void
{
$stmt = $this->pdo->prepare('
INSERT INTO videos (id, title, description, thumbnail, channel_id, channel_title, category_id, region, published_at, fetched_at)
VALUES (:id, :title, :description, :thumbnail, :channel_id, :channel_title, :category_id, :region, :published_at, :fetched_at)
ON CONFLICT(id, region) DO UPDATE SET
title = excluded.title,
thumbnail = excluded.thumbnail,
fetched_at = excluded.fetched_at
');
$stmt->execute($video);
}
}
Region Configuration
Each server has its own region assignments:
<?php
enum Region: string
{
case US = 'US';
case GB = 'GB';
case CH = 'CH';
case DK = 'DK';
case AE = 'AE';
case BE = 'BE';
case CZ = 'CZ';
case FI = 'FI';
}
// Server-specific config
const FETCH_REGIONS = [Region::US, Region::GB, Region::CH, Region::DK, Region::AE, Region::BE, Region::CZ, Region::FI];
The Fetch Pipeline
The cron job runs a multi-step pipeline:
<?php
class VideoFetcher
{
public function run(): void
{
// Step 1: Fetch popular videos
$this->fetchPopular();
// Step 2: Update categories
$this->updateCategories();
// Step 3: Region-specific trending
foreach (FETCH_REGIONS as $region) {
$this->fetchTrending($region);
usleep(500000); // Rate limiting
}
// Step 4: Refresh stale entries
$this->refreshStale();
// Step 5: Cleanup old data
$this->cleanup();
// Step 6: Rebuild search index
$this->rebuildIndex();
}
}
Caching Strategy
The 3-tier cache keeps the platform fast:
<?php
class Cache
{
const int TTL_CATEGORIES = 86400; // 24 hours
const int TTL_HOME = 10800; // 3 hours
const int TTL_WATCH = 21600; // 6 hours
const int TTL_SEARCH = 600; // 10 minutes
public function get(string $key): mixed
{
$file = $this->path($key);
if (!file_exists($file)) return null;
$data = unserialize(file_get_contents($file));
if ($data['expires'] < time()) {
unlink($file);
return null;
}
return $data['value'];
}
public function set(string $key, mixed $value, int $ttl): void
{
file_put_contents($this->path($key), serialize([
'value' => $value,
'expires' => time() + $ttl,
]));
}
}
You can see this architecture in action at TrendVidStream, where it handles trending video aggregation from all 8 regions.
Conclusion
PHP 8.3 + SQLite + LiteSpeed is a powerful combination for content platforms. The stack is simple, cheap to host, and performs well. Sometimes boring technology is the best technology.
Check out trendvidstream.com to see the platform live.
Why This Stack Works for Global Platforms
The combination of PHP 8.3, SQLite, and LiteSpeed might seem unconventional for a platform serving 8 countries, but it excels for several reasons.
First, deployment is trivially simple. Each server is self-contained with its own database file. There are no cross-server dependencies, no shared database connections, and no replication to manage. When we deploy to all 4 servers simultaneously via FTP, each one gets a complete, independent application.
Second, the cost is remarkably low. Four shared hosting plans total under $50 per month. Compare this to a managed Kubernetes cluster, a PostgreSQL database, and a Redis cache, which could easily cost $200-500 per month for a similar workload.
Third, SQLite performs excellently for our read-heavy workload. With WAL mode enabled and proper indexing, query times are measured in single-digit milliseconds. The 3-tier cache means most requests never hit the database at all.
The architecture behind TrendVidStream proves that global platforms do not require complex infrastructure. What matters is choosing the right tool for the actual workload, not the theoretical one.
What is Next
Future improvements include adding more regions, implementing cross-region video deduplication, and building a public API for researchers interested in comparative trending analysis. The modular architecture makes these additions straightforward without rearchitecting the core system.
Top comments (0)