Retro Price
901,713 sold-price records across 3,753 titles by the Mar 2026 snapshot; main app now offline
For physical-media collectors (VHS, DVD, Blu-ray, LaserDisc, 4K UHD) who need real sold comps, not asking prices, to decide when to buy or sell.
At a glance
- Role
- Creator and technical lead (solo)
- Timeframe
- Aug 2025 (data collection start) – Mar 2026 snapshot
- Team
- Solo (AI-assisted with Claude Code)
- Users
- No user numbers published
- Status
- Main app offline; standalone build showcase live (Mar 2026 snapshot)
- Stack
- PHP 8.x, Python 3.12, PostgreSQL (JSONB), Redis, scikit-learn, Alpine.js
Problem and stakes
Physical-media prices are volatile and hard to read. Asking prices mislead, graded copies sell for many times more than ungraded ones, and community buzz moves prices before listings show it. Collectors need comps based on actual sold data.
Constraints
The eBay API allows 5,000 calls a day, shared across every operation. Live API calls made search take 5–10 seconds. Reddit title extraction was noisy: in early runs, 68% of extracted titles were false positives.
Options considered
Live API search vs. a database-first architecture: live calls were too slow, so search moved to precomputed local data.
Decision
Go database-first. Ingest sold listings on a schedule, store raw payloads as JSONB, and serve search and price guides from PostgreSQL aggregates. Score market "waves" from scarcity, Reddit momentum, and seasonality, and separate graded from ungraded items so premiums don't skew the statistics.
Program plan
Phase 1: PostgreSQL schema, eBay OAuth integration, TMDB/OMDb metadata. Phase 2: Reddit trending, graded-item detection, wave analysis. Phase 3: database-backed search, Alpine.js frontend, price guide. Phase 4: production hardening (SSL, Nginx headers, rate-limiter fixes, OPcache, daily pipeline).
Technical system
PHP handles the web app and API integrations, and Python runs ML and heavy analysis. A cron pipeline runs twice daily in five steps: TMDB-driven eBay crawl across all formats, Reddit trending scan (16 collector subreddits), AI price analysis, wave analyzer, and ML predictions.
Wave score (0–100) = scarcity 40% + Reddit 40% + seasonality 20%, mapped to Peak, Heating up, Stable, Cooling, and Bottom. A weekly scikit-learn retrain on 7-day price change is blended with the rules.
Graded items (VGA, WATA, CGC, PSA, factory sealed) are detected by PostgreSQL regex functions. Other sources: Heritage Auctions, Goodwill deal polling, and Amazon new releases. Public v1 read APIs use keys and rate limits.
Execution
Moving search to the database cut response times from 5–10 seconds of live API calls to about 150–200 ms. Reddit false positives were reduced with a blacklist, proper-noun and length checks, and confidence levels. An infinite "Searching..." spinner was traced to four causes: Alpine.js not loaded, over-strict validation, a rate limiter returning the wrong type, and unnormalized format strings.
Outcome
Production snapshot (Mar 2026, from the live showcase): 901,713 price records, 3,753 titles with comps, 3,770 catalog titles, and 38,075 wave analyses. By format: DVD 376,539 listings, Blu-ray 293,176, 4K UHD 154,007, LaserDisc 73,453, VHS 4,538. The data also surfaced surprise valuations such as Akira (1988) on VHS averaging $1,543.99 sold. The main app is now offline, and the showcase is the standing artifact.
Reflection
Database-first beats API-first for data people look up often. JSONB adds flexibility without schema churn. Rate limits push you toward creative caching. Documenting during development is easier than reconstructing it afterward.