Deploy the Matchy Slack bot to Koyeb's free tier using Socket Mode. A keep-alive ping prevents Koyeb from scaling the service to zero after 1 hour of inactivity.
- Socket Mode: No public URL needed for Slack—the bot connects outbound to Slack
- Free Tier: 1 web service, 512MB RAM, 0.1 vCPU (Frankfurt or Washington, D.C.)
- Keep-Alive: UptimeRobot pings
/healthevery 30 minutes to prevent scale-to-zero
- Go to Koyeb and sign up (no credit card needed for Hobby in most regions)
- Create a new Web Service
- Source: Connect your GitHub repo and select this project
- Build:
- Builder: Nixpacks (default) or Dockerfile
- Build command: (leave default, or
npm install) - Run command:
node app.js
- Instance: Select the Free instance type (512MB RAM)
- Region: Frankfurt or Washington, D.C. (free tier regions)
- Port:
8000(or setPORTenv var to match) - Environment Variables: Add the following (Settings → Environment variables)
| Variable | Description |
|---|---|
SLACK_TOKEN |
Bot OAuth token (xoxb-...) |
SIGNING_SECRET |
Signing secret from Slack app |
APP_LEVEL_TOKEN |
App-level token for Socket Mode (xapp-...) |
FIREBASE_API_KEY |
Firebase config |
FIREBASE_AUTHDOMAIN |
Firebase config |
FIREBASE_PROJECTID |
Firebase config |
FIREBASE_STORAGEBUCKET |
Firebase config |
FIREBASE_MESSAGINGSENDERID |
Firebase config |
FIREBASE_APPID |
Firebase config |
MATCHY_CHANNEL_ID |
(Optional) Slack channel for matchy results |
PORT |
(Optional) 8000 — Koyeb usually sets this automatically |
- Deploy and note your app URL (e.g.
https://your-app-name.koyeb.app)
Koyeb's free tier scales to zero after 1 hour of no incoming traffic. Socket Mode uses outbound connections, so we need a periodic HTTP ping to count as "incoming traffic."
- Go to UptimeRobot (free tier)
- Add New Monitor
- Monitor Type: HTTP(s)
- URL:
https://your-app-name.koyeb.app/health - Monitoring Interval: 5 minutes (or 30 minutes if on free limits)
- Save
UptimeRobot will ping your app regularly. As long as the interval is less than 1 hour, Koyeb will not scale your service to zero.
- Go to Cron-job.org (free)
- Create a new cron job
- URL:
https://your-app-name.koyeb.app/health - Schedule: Every 30 minutes (e.g.
*/30 * * * *) - Save
- Go to api.slack.com/apps → your app
- Socket Mode: Turn ON
- OAuth & Permissions: Ensure your bot has the required scopes
- Event Subscriptions: Not required for Socket Mode (the bot connects to Slack, not vice versa)
The app uses node-schedule to run matchy every Wednesday at 5 PM PST. As long as the app stays running (kept awake by UptimeRobot), this happens automatically—no GitHub Actions or external cron needed.
| Endpoint | Method | Purpose |
|---|---|---|
/ |
GET | Simple "Bot is running" (keep-alive) |
/health |
GET | JSON health check (keep-alive) |
/matchy-scheduled |
POST | Manual trigger for matchy (optional; requires CRON_SECRET env var) |
- Bot goes offline after ~1 hour: Ensure UptimeRobot (or similar) is pinging your app more frequently than every 60 minutes
- Slash commands not responding: Check Slack app has Socket Mode enabled and
APP_LEVEL_TOKENis set - Matchy not running: Check Koyeb logs to verify
node-scheduleis running (app must stay awake via UptimeRobot)
npm run devUses http://localhost:8000. Socket Mode works locally without exposing a public URL.