260MB for a personal analytics dashboard. Just tracking 4,000 events across 21 websites over 5 days. Barely any data, but my Bun server was eating 150MB and TimescaleDB was claiming 120MB like it was serving a production SaaS.
On Railway's usage-based $5 plan, every MB counts. Time to optimize.
The Stack
- Server: Bun + Hono + Drizzle ORM + Better-Auth
- Database: TimescaleDB (PostgreSQL for time-series data)
- Cache: Redis
- Frontend + Proxy: Nginx serving Vite/React SPA with reverse proxy to backend
Server Optimizations (150MB → 50-60MB)
- Removed unused OpenAPI/Zod schema introspection - heavy libs not needed for single-user project
-
Used Bun's
--smolflag - smaller memory footprint GC with more aggressive garbage collection. Minimal perf impact for low-traffic apps. This one's a hidden gem. -
Removed
--sourcemapand--bytecode- unnecessary overhead in production binaries
TimescaleDB Optimizations (100-120MB → 60-80MB)
The TimescaleDB defaults were completely overkill for a personal project:
| Setting | Default | Optimized | What it does |
|---|---|---|---|
shared_buffers |
1907MB | 128MB | Memory for caching table/index data. Default was set to 25% of RAM - insane for a personal project |
maintenance_work_mem |
953MB | 64MB | Memory for VACUUM, CREATE INDEX, etc. Almost 1GB for maintenance ops! |
work_mem |
2.4MB | 4MB | Memory per query operation (sorts, joins). This was already reasonable |
max_background_workers |
16 | 8 | Workers for chunk compression/maintenance. Halved but still plenty |
telemetry_level |
basic | off | Disables TimescaleDB telemetry. Saves CPU cycles and network calls |
-- Memory settings (tuned down for single-user workload)
ALTER SYSTEM SET shared_buffers = '128MB';
ALTER SYSTEM SET maintenance_work_mem = '64MB';
ALTER SYSTEM SET work_mem = '4MB';
-- TimescaleDB settings
ALTER SYSTEM SET timescaledb.max_background_workers = '8';
ALTER SYSTEM SET timescaledb.telemetry_level = 'off';
SELECT pg_reload_conf();
Results
| Component | Before | After | Reduction |
|---|---|---|---|
| Bun Server | 150MB | 55MB | -63% |
| TimescaleDB | 110MB | 70MB | -36% |
| Redis | 8MB | 8MB | Already lean |
| Nginx + Frontend | 35MB | 35MB | Already lean |
| Total | ~300MB | ~170MB | -45% |
From a memory-hungry pet project to something a Raspberry Pi could handle without breaking a sweat.
Key Takeaway
Don't assume defaults are right for your use case. A personal project doesn't need the same configuration as a high-traffic SaaS. Right-size your infrastructure - that 130MB headroom means I can spin up another test project or two without bumping tiers.
Top comments (0)