Fly.io runs your app on servers around the world, close to your users. It's great for global teams and offers competitive pricing with a generous free tier.
Why Fly.io?
- Global edge deployment
- Built-in Redis (Upstash integration)
- Generous free tier (3 shared VMs)
- Simple CLI-based deployment
- Automatic SSL and load balancing
Prerequisites
- A GitHub account
- Fly.io account (sign up at fly.io)
- Fly CLI installed (
brew install flyctlor see fly.io/docs/hands-on/install-flyctl) - MongoDB Atlas account for database
Step 1: Set Up MongoDB Atlas
- Create a free cluster at mongodb.com/atlas
- Set up a database user and note the password
- In Network Access, allow connections from
0.0.0.0/0 - Get your connection string from Connect → Connect your application
Step 2: Initialize Fly.io App
Navigate to your Maillayer directory and run:
fly auth login
fly launch
When prompted:
- Choose an app name (e.g.,
maillayer-production) - Select a region close to you
- Say No to setting up a PostgreSQL database
- Say No to setting up an Upstash Redis (we'll add it separately)
- Say Yes to deploy now? No (we need to configure first)
Step 3: Create Upstash Redis on Fly
Fly.io has native Upstash Redis integration:
fly redis create
Select:
- A name like
maillayer-redis - The same region as your app
- Choose Free plan for testing or a paid plan for production
Copy the Redis URL from the output.
Step 4: Configure Secrets
Set your environment variables as secrets:
fly secrets set NODE_ENV=production
fly secrets set BASE_URL=https://maillayer-production.fly.dev
fly secrets set NEXTAUTH_SECRET=your-secret-key-minimum-32-characters
fly secrets set TRACKING_SECRET=your-tracking-secret
fly secrets set MONGODB_URI="mongodb+srv://user:pass@cluster.mongodb.net/maillayer"
fly secrets set REDIS_URL="redis://default:password@your-redis.upstash.io:6379"
Step 5: Configure fly.toml
Your fly.toml should look like this:
app = "maillayer-production"
primary_region = "ord"
[build]
dockerfile = "Dockerfile"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 512
Important: Set auto_stop_machines = false to keep workers running.
Step 6: Deploy
fly deploy
Wait 3-5 minutes for the build and deployment. Access your app at https://your-app.fly.dev.
Step 7: Add Custom Domain (Optional)
fly certs add mail.yourdomain.com
Follow the DNS instructions provided, then update your BASE_URL:
fly secrets set BASE_URL=https://mail.yourdomain.com
Monitoring & Logs
View real-time logs:
fly logs
Monitor your app:
fly status
fly dashboard
Scaling
Scale memory for high-volume email processing:
fly scale memory 1024
Add more instances:
fly scale count 2
Estimated Costs
| Resource | Free Tier | Production |
|---|---|---|
| Compute | 3 shared VMs free | ~$5-10/month |
| Redis (Upstash) | 10k commands/day | ~$5-10/month |
| MongoDB Atlas | Free M0 | ~$9/month |
Total: Free to start, ~$15-25/month for production.
Troubleshooting
App keeps stopping
- Ensure
auto_stop_machines = falsein fly.toml for worker processes.
Build runs out of memory
- Use a larger builder:
fly deploy --build-remote
Redis connection refused
- Verify the Redis URL includes the password. Check with
fly redis status.
MongoDB connection timeout
- Ensure MongoDB Atlas allows connections from all IPs (
0.0.0.0/0).
