Monorepos are powerful, but when it comes to deploying them to platforms like Koyeb, Netlify, and Vercel, things can get messy fast.
In this article, I’ll walk you through a common issue with monorepo deployments and how I solved it using GitHub Actions, including how to disable auto-deployments and trigger deploys only when specific apps/packages change.
🧠 The Problem
Modern deployment platforms listen to your repo and redeploy your app every time anything changes. This works fine for single-app projects.
But with monorepos? Not so much.
Imagine this:
- You have a monorepo with multiple packages or apps.
- You deploy only one package to a platform like Vercel.
- Then you change a file in another unrelated package.
- The platform still triggers a redeploy 😩
That’s a waste of resources, time, and can cause unnecessary build failures.
We want this instead:
Only deploy when files relevant to the deployed app/package are changed.
🗂️ Example Project Structure
To demonstrate the solution, let’s use a simple monorepo setup like this:
monorepo/
├── netlify-frontend/ # Deployed to Netlify
├── vercel-nextjs-app/ # Deployed to Vercel
├── koyeb-server/ # Deployed to Koyeb
└── shared/ # Shared code across apps (not deployed directly)
🔑 Generating Deployment Credentials
Before we disable auto-deploys, we need a way to trigger deploys manually — using webhooks or API keys.
Vercel – Deployment Webhook
- Navigate to your project page → Settings → Git → Deploy Hooks → Create Hook
Netlify – Build Hook
- Go to your site dashboard → Site Configuration → Build & Deploy → Build Hooks → Add Build Hook
Koyeb – API Key
Koyeb doesn’t use build hooks, but instead offers an API you can use to trigger deployments programmatically.
- Open your Koyeb dashboard → Settings → API → Create API Token
🚫 Disabling Auto-Deployments
Once we have the credentials, we can safely disable automatic deployments.
Netlify
- Go to your site dashboard → Deploys → Click Lock to stop auto publishing
Vercel
To prevent auto-deploys from Git integration:
- Navigate to your project page → Settings → Git → Ignored Build Step → Select "Don't build anything"
Koyeb
To disable Git auto-deploy:
- Go to your service page → Settings → Configure Deployment Source → Uncheck the Autodeploy checkbox
⚙️ Step 2: GitHub Actions Workflow
Now that auto-deploy is off, we take control.
Here’s how the GitHub Actions workflow works:
- It checks what files or folders have changed in the commit.
- If the changed files are part of
netlify-frontend/
,vercel-nextjs-app/
, orkoyeb-server/
, it triggers the corresponding deployment via webhook/API.
Here’s a sample workflow:
# .github/workflows/deploy.yml
name: Conditional Deploy
on:
push:
branches:
- master # Triggers workflow only on push to master branch
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
# Expose matched filters as outputs for use in other jobs
netlify_frontend_changed: ${{ steps.filter.outputs.netlify_frontend }}
vercel_nextjs_app_changed: ${{ steps.filter.outputs.vercel_nextjs_app }}
koyeb_server_changed: ${{ steps.filter.outputs.koyeb_server }}
shared_changed: ${{ steps.filter.outputs.shared }}
steps:
- uses: actions/checkout@v3 # Checkout the repository code
- name: Check for changes
id: filter
uses: dorny/paths-filter@v3 # Detect which paths have changed
with:
filters: |
netlify_frontend:
- 'netlify-frontend/**'
vercel_nextjs_app:
- 'vercel-nextjs-app/**'
koyeb_server:
- 'koyeb-server/**'
shared:
- 'shared/**'
deploy-netlify-frontend:
needs: detect-changes
if: needs.detect-changes.outputs.netlify_frontend_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger Netlify Deploy
run: |
curl -X POST -d '{}' https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_FRONTEND_DEPLOY_KEY }}
# Uses Netlify build hook URL to trigger deploy
deploy-nextjs-app:
needs: detect-changes
if: needs.detect-changes.outputs.vercel_nextjs_app_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Trigger Vercel Deploy
run: |
curl -X POST -d '{}' https://api.vercel.com/v1/integrations/deploy/${{ secrets.VERCEL_APP_DEPLOY_KEY }}
# Uses Vercel deploy webhook to trigger a deploy
deploy-koyeb-server:
needs: detect-changes
if: needs.detect-changes.outputs.koyeb_server_changed == 'true' || needs.detect-changes.outputs.shared_changed == 'true'
runs-on: ubuntu-latest
steps:
- name: Install Koyeb CLI
run: |
curl -fsSL https://raw.githubusercontent.com/koyeb/koyeb-cli/master/install.sh | sh
echo "$HOME/.koyeb/bin" >> $GITHUB_PATH
# Installs the Koyeb CLI and adds it to the path
- name: Verify CLI
run: koyeb version
# Optional step to verify the CLI is working
- name: Trigger redeploy
run: |
koyeb service redeploy ${{ secrets.KOYEB_SERVICE_NAME }} \
--app ${{ secrets.KOYEB_APP_NAME }} \
--token ${{ secrets.KOYEB_API_TOKEN }}
# Redeploys the Koyeb service using the CLI and secret tokens
🎯 Final Thoughts
With this setup:
✅ You stop wasting build minutes
✅ You only deploy what's actually changed
✅ You fully control the pipeline with GitHub Actions
Let your monorepo breathe — deploy smarter, not harder.