Server Radar is a tool that tracks the prices of Hetzner's Dedicated Server Auction over time, helping customers identify the best configurations and prices. While Hetzner's auction site allows filtering by certain criteria, it only provides a snapshot at a given moment. Server Radar aims to enhance this by offering advanced filtering, a comprehensive pricing history and target price alerts. Additionally, we track server volumes and other relevant statistics.
[!NOTE] This is an independent project and is not officially affiliated with Hetzner. "Hetzner" is a trademark owned by its respective owners. This project does not claim any official endorsement by Hetzner, nor does it guarantee correctness of the data. Use at your own risk.
Server Radar started as a purely static, client-side application where users could browse and filter server data entirely in their browser using DuckDB WASM. When we introduced the alerts feature, we needed persistent storage and notification capabilities, which led to the current hybrid architecture.
Today, the project uses both client- and backend components, with the website statically built using SvelteKit. DuckDB is still used for querying the database on the client, while Cloudflare Workers handle session management, storing alerts and sending email notifications (using D1 for backend storage).
Auction data is fetched from Hetzner every 5 minutes via two parallel pipelines:
The DuckDB database is updated incrementally - each run fetches the current snapshot from Hetzner, merges it with existing data (keeping one record per auction per day), and automatically purges data older than 90 days.
The project is deployed on Cloudflare Pages. Looking ahead, we plan to transition to a backend-only architecture, eliminating client-side DuckDB entirely.
As part of our transition to a backend-only architecture, we're implementing a dual-table storage strategy for auction data in the backend (Cloudflare D1):
auctions table: Stores historical auction data with intelligent deduplication - only creates new entries when server prices or specifications change. This preserves a complete pricing history while eliminating redundant data.
current_auctions table: Maintains the current state of all active auctions (one row per auction). This table is continuously updated with the latest auction data, regardless of whether prices have changed.
This backend storage approach significantly reduces D1 database reads by:
current_auctions table (~100K records) instead of the full historical dataset (~1M+ records)current_auctions table has specialized indices for efficient alert matchingAuction data is imported every 5 minutes from Hetzner's API directly by our Cloudflare Worker (AuctionImportDO), with only price changes and new listings being stored in the historical auctions table, while all current states are refreshed in current_auctions. This backend storage complements the existing client-side DuckDB approach during the architectural transition.
The alert system has been redesigned with a worker-based architecture for improved reliability and performance:
Alert Processing Flow:
Notification Channels:
Key Features:
The legacy push endpoint (/api/push) is deprecated but maintained temporarily for backward compatibility. All new alert processing happens automatically in the worker during auction imports.
Cloud availability alerts use the same worker-based architecture for consistent performance and reliability:
Cloud Alert Processing Flow:
Integration Benefits:
The legacy notify endpoint (/api/notify) is deprecated but maintained temporarily for backward compatibility. All new cloud alert processing happens automatically in the worker during cloud status updates.
To set up your development environment, you'll need:
This step is optional if you just want to work on the frontend. You can simply download the latest snapshot from the website:
wget https://static.radar.iodev.org/sb.duckdb -O static/sb.duckdb
If you just want to inspect or play with the dataset, you can do so by running:
duckdb -cmd "attach 'https://static.radar.iodev.org/sb.duckdb' (read_only); use sb;"
Inspect the schema using the .schema pragma.
To manually update the database with the latest data:
cd scripts
poetry install
poetry run python update_incremental.py ../static/sb.duckdb
The worker handles multiple functions including auction data fetching, cloud availability tracking, and alert notifications. To run it locally:
.dev.vars file in the worker directory:# create a token via the Hetzner Cloud console
HETZNER_API_TOKEN=your_hetzner_api_token_here
# this is an internal API key used when notifying the backend
API_KEY=your_api_key_here
# API key for ForwardEmail service (for alert notifications)
FORWARDEMAIL_API_KEY=your_forwardemail_api_key_here
cd worker
npm install
npx wrangler dev
The worker will start on port 8787 by default. Keep this terminal window open.
For local development, the worker exposes HTTP debug routes at http://localhost:8787. Visit any invalid endpoint to see available routes and usage examples.
# In the project root
npm install
npm run dev
The application will be available at http://localhost:5123. If the worker is running, the backend can automatically interact with it for cloud availability tracking and auction processing.
Contributions are welcome and encouraged! Whether it's fixing a bug, adding a new feature, or optimizing performance, your input can make Server Radar even better. If you have an idea or a patch, feel free to submit a pull request or open an issue.
Before contributing, please ensure that your changes align with the project's goals and architecture. If you're unsure or would like to discuss your ideas, don't hesitate to start a discussion in the issues section.
I'm happy to review and merge any meaningful contributions that improve the project. Thank you for helping to make Server Radar better for everyone!
The initial version of Server Radar was entirely hand-crafted, serving as a learning project for SvelteKit and DuckDB. As the project evolved, we began incorporating AI tools to accelerate development - first using Roo, and now primarily Claude Code. Some features and website content (like testimonials) were added just for fun and are entirely fictional - don't take everything too seriously! This blend of manual craftsmanship, AI assistance, and creative liberties has made the project what it is today.
This project was created by a satisfied Hetzner customer and is intended in good faith. The project is designed to be beneficial for all parties involved. If you have any concerns, please reach out.
Please note that this is an independent project and is not officially affiliated with Hetzner. "Hetzner" is a trademark owned by its respective owners. This project does not claim any official endorsement by Hetzner, nor does it guarantee correctness of the data. Use at your own risk.
$ claude mcp add hetzner-radar \
-- python -m otcore.mcp_server <graph>