Back to Blog

January 31, 2026

The "Broke Indie Dev" MMORPG Stack: Running a Godot + Rust MMO on $0/Month

How we built a scalable MMORPG backend using Oracle Cloud, GCP, IBM Cloud, and smart architectural decisions—without spending a dime.


The Challenge

Building an MMORPG is hard. Building an MMORPG infrastructure is harder. And doing it with zero budget? That's where creativity meets constraints.

Every indie game dev faces the same nightmare: you have a Godot engine frontend, a blazingly fast Rust backend, and dreams of thousands of concurrent players. But then you look at AWS pricing calculators and realize your life savings won't cover a month of EC2 instances.

Enter the "Free Tier Gang"—a distributed architecture leveraging the generosity (or marketing budgets) of major cloud providers.

The Stack Overview

We built a three-node distributed system using the "Always Free" tiers of major cloud providers:

  1. Oracle Cloud (Arm Ampere A1) - 4 OCPUs, 24GB RAM, 200GB storage
  2. Google Cloud Platform (e2-micro) - 1 vCPU, 1GB RAM, 30GB disk
  3. IBM Cloud (Lite VPS) - 2 vCPUs, 4GB RAM, 25GB storage

Total monthly cost: $0.00

Architectural Philosophy: Separation of Concerns

Oracle Cloud: The Arena (Game Server)

Role: Primary Rust MMORPG backend
Deployment: Native binary via systemd (no Docker)
Why: Network latency is king in real-time games

Oracle's Arm-based free tier is the crown jewel here. 24GB RAM is absurdly generous—we're talking enough headroom for thousands of concurrent connections.

Critical Decision: We run the game server as a native binary, not in Docker. When you're handling 60 UDP ticks per second with thousands of players, that extra 0.5-2ms overhead from Docker's NAT layer matters. Every microsecond counts when you're calculating collision detection or PvP combat resolution.

# Native execution for Oracle
./mmorpg-server --release

Google Cloud Platform: The Matchmaker

Role: Matchmaking service, lobby coordination
Deployment: Rust binary + Docker Compose (no Dokploy)
Why: 1GB RAM is too tight for Dokploy overhead

GCP's e2-micro is too constrained for Dokploy (which needs ~1GB just for its own stack), but perfect for a lightweight matchmaking service. We skip the heavy container orchestration and use a simple systemd service or Docker Compose for the matchmaker.

Matchmaking doesn't need the same blistering performance as the game loop—it's HTTP/gRPC based, stateless, and can tolerate slightly higher latency.

IBM Cloud: The Command Center (Web API + Admin Panel)

Role: REST API, admin dashboard, analytics
Deployment: Dokploy (with Traefik)
Why: 4GB RAM is the sweet spot for Dokploy + web services

Here's where Dokploy shines. The admin panel is standard web fare—HTTP requests, database queries, React/Vue frontend served by Actix-web or Axum. We deploy this with Dokploy because:

  • Automatic HTTPS via Let's Encrypt
  • Git-based deployments (git push → auto build)
  • PostgreSQL management via UI
# IBM gets the full Dokploy treatment
curl -sSL https://dokploy.com/install.sh | sudo sh

Where Dokploy Fits (And Where It Doesn't)

Install Dokploy on:

  • Oracle: Yes, but only for auxiliary services (web dashboard, Postgres if not using Aiven). Keep the game server native.
  • IBM: Yes, this is your primary Dokploy node for web-facing services.

Skip Dokploy on:

  • GCP: 1GB RAM gets eaten by Dokploy's infrastructure (Traefik, Postgres, Redis, monitoring). You'll have 200MB left for your actual app, leading to OOM kills.

The Secret Weapon: Tailscale Mesh

Three VPSs in different clouds need to talk to each other securely. Opening public ports between them is a security nightmare. Instead, we use Tailscale to create a private mesh network:

Oracle (Game Server) ----Tailscale----> GCP (Matchmaking)
     |                                      |
     |                                  Tailscale
     |                                      |
     +----Tailscale----> IBM (Admin/API) <---+

All services communicate via private 100.x.x.x IPs. The database connection string in your Oracle server becomes postgres://tailscale-ip:5432 instead of exposing GCP's public IP. Zero-config firewall rules between your infra.

Database Strategy: Don't Host Postgres on Your Game Server

Here's where most indie devs mess up: they install PostgreSQL on their beefy Oracle VPS and wonder why their game lags during database writes.

Solution: Use external managed databases like Aiven.io, Supabase, or Neon. They offer generous free tiers (5-10GB storage),专业的 maintenance, and you keep your Oracle VPS focused purely on game logic.

If you must self-host, put Postgres on the IBM instance (Dokploy makes this trivial), not Oracle.

Godot + Rust: A Match Made in Performance Heaven

Frontend: Godot 4.x (GDExtension or GDScript)
Protocol: WebSocket for reliable messages (chat, inventory), UDP for real-time (position, combat)
Backend: Rust (Actix-web or Axum for HTTP, custom UDP socket for game loop)

Why this combo?

  • Godot's networking is solid but not MMO-grade. Rust handles the heavy lifting.
  • Rust's zero-cost abstractions mean your game server saturates the network before CPU hits 100%.
  • Godot communicates with Oracle via UDP for game state, with IBM via REST API for player data.

Logging in Production: JSON Everywhere

We use tracing with tracing-bunyan-formatter for structured JSON logs. Yes, they look ugly in the Dokploy UI:

{"v":0,"name":"mmorpg-server","msg":"Player connected","level":30,"pid":1,"time":"2026-01-31T00:00:00Z","player_id":12345}

But this is intentional. When debugging, SSH in and pipe through jq:

docker logs mmorpg-server -f | jq '.msg, .player_id'

Don't pretty-print logs in production—it breaks log aggregation and adds unnecessary bytes to your bandwidth bill.

Performance Checklist

Before you go live, verify these:

  1. Native binary on Oracle: cargo build --release, deploy binary + systemd service
  2. UDP optimization: Increase kernel UDP buffers (sysctl -w net.core.rmem_max=...)
  3. No Docker for game loop: Use containers only for stateless web services
  4. Connection pooling: Postgres connections pool on IBM, not Oracle game server
  5. Monitoring: Check docker stats on IBM, htop on Oracle to ensure you're not hitting limits

The Reality Check

This setup can handle 2,000-5,000 concurrent players easily. After that, you'll need to:

  • Shard your game worlds (multiple Oracle instances)
  • Move to paid tiers (Hetzner Cloud at €3/month is cheaper than AWS/GCP paid tiers)
  • Implement regional edge nodes for lower latency

But for alpha testing, closed beta, or a niche indie MMO? This stack is production-grade and costs nothing.

Conclusion

The "big three" free tier providers (Oracle, GCP, IBM) combined with Dokploy on the right nodes, native binaries where it counts, and Tailscale for security create a surprisingly robust MMORPG infrastructure.

It's not just about saving money—it's about architectural discipline. When you're constrained to 1GB RAM on a node, you write efficient code. When you're managing three separate VPSs, you design clean service boundaries. These constraints make your game better.

Now go forth and build worlds. The infrastructure is waiting, and your wallet will thank you.


Stack Recap:

  • Oracle: Native Rust game server (no Dokploy for main binary)
  • GCP: Native Rust matchmaking (no Dokploy, low RAM)
  • IBM: Dokploy + Web API/Admin + Traefik
  • Networking: Tailscale mesh between all three
  • Database: Aiven/Supabase (external) or Postgres on IBM via Dokploy
  • Frontend: Godot Engine
  • Logs: Structured JSON (Bunyan format), viewed with jq