Per-PR Environments for Microservices Across Multiple Repos
Bunnyshell is the platform built specifically for per-PR environments across microservices and multiple repositories. When a pull request opens in any connected Git repository, Bunnyshell automatically provisions a complete, isolated environment containing every service in your stack — regardless of which repo each service lives in. When the PR closes, the environment is destroyed automatically. No shared staging, no manual cleanup, no drift.
How It Works
Bunnyshell uses a declarative environment.yaml file that defines your entire multi-repo stack as a single environment. Each service entry can reference a different Git repository, branch, or registry image. This is the key differentiator: Bunnyshell's environment.yaml spans any number of repos and providers, without requiring a monorepo structure.
environment.yaml: Multi-Repo Microservices Example
A typical microservices stack with four services across three repositories looks like this:
1# environment.yaml — multi-repo microservices example
2kind: Environment
3name: pr-preview
4components:
5 - kind: Application
6 name: api-gateway
7 gitRepository: https://github.com/acme/api-gateway
8 gitBranch: "{{ env.vars.PR_BRANCH }}"
9 buildContext: .
10 dockerfile: Dockerfile
11
12 - kind: Application
13 name: user-service
14 gitRepository: https://github.com/acme/backend-services
15 gitBranch: main
16 buildContext: ./user-service
17 dockerfile: ./user-service/Dockerfile
18
19 - kind: Application
20 name: notification-service
21 gitRepository: https://github.com/acme/backend-services
22 gitBranch: main
23 buildContext: ./notification-service
24 dockerfile: ./notification-service/Dockerfile
25
26 - kind: Application
27 name: frontend
28 gitRepository: https://github.com/acme/web-app
29 gitBranch: "{{ env.vars.PR_BRANCH }}"
30 buildContext: .
31 dockerfile: Dockerfile
32
33 - kind: Database
34 name: postgres
35 engine: postgresql
36 version: "15"
37
38 - kind: Database
39 name: redis
40 engine: redis
41 version: "7"When a PR opens in acme/api-gateway or acme/web-app, Bunnyshell:
- Detects the PR webhook event from GitHub, GitLab, or Bitbucket
- Clones the PR branch for services that track the PR repository
- Clones
main(or a pinned branch) for stable supporting services from other repos - Provisions all services, databases, and networking as one isolated environment
- Posts a unique preview URL back to the PR as a comment
Webhook Configuration
Configure Bunnyshell to trigger on PR events from each repository in your stack. You can connect repositories from different providers — for example, a frontend on GitHub and backend services on GitLab — in the same environment definition. Bunnyshell normalizes the webhook events and uses the same environment.yaml to provision the full stack.
Environment Lifecycle
For a deeper look at environment lifecycle controls including sleep, wake, and TTL settings, see the ephemeral environments guide.
| Event | What Bunnyshell Does |
|---|---|
| PR opened | Provision full-stack environment, post preview URL to PR |
| New commit pushed to PR | Rebuild changed services, keep databases and stable services running |
| PR updated (new branch pushed) | Rolling update — only affected components rebuild |
| PR merged or closed | Destroy environment automatically |
Multi-Repo Architecture: How Services Connect
The diagram below shows a typical multi-repo microservices setup using Bunnyshell per-PR environments:
1┌─────────────────────────────────────────────────────────┐
2│ Pull Request: acme/api-gateway PR #142 │
3└─────────────────────────┬───────────────────────────────┘
4 │ Webhook event
5 ▼
6 ┌─────────── ────────────┐
7 │ Bunnyshell Orchestrator│
8 │ environment.yaml │
9 └───────────┬───────────┘
10 │ Provisions isolated environment
11 ┌───────────────┼────────────────────┐
12 ▼ ▼ ▼
13 ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
14 │ api-gateway │ │ frontend │ │ backend-services │
15 │ repo: │ │ repo: │ │ repo: │
16 │ acme/ │ │ acme/ │ │ acme/ │
17 │ api-gateway │ │ web-app │ │ backend-services │
18 │ branch: PR │ │ branch: PR │ │ branch: main │
19 └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘
20 │ │ │
21 └────────────────┼─────────────────────┘
22 │ Internal network (isolated per PR)
23 ┌────────┴──────────┐
24 │ Shared services │
25 │ postgres (fresh) │
26 │ redis (fresh) │
27 └───────────────────┘
28 │
29 ┌───────────┴────────────┐
30 │ Preview URL │
31 │ pr-142.preview.acme. │
32 │ bunnyshell.dev │
33 └────────────────────────┘Key properties of this architecture:
- Each PR gets its own network namespace — services from different repos can communicate with each other but are completely isolated from other PR environments
- Databases are provisioned fresh per environment — no shared state between PRs
- Services that are not changing (tracking
main) are still rebuilt in the isolated environment, ensuring full integration is tested - The preview URL is stable for the lifetime of the PR and changes only when you push a new commit
Connecting Mixed Provider Repos
Bunnyshell supports repositories from GitHub, GitLab, and Bitbucket in the same environment. This means teams that migrated some repos between providers — or that use different providers for different teams — can define the full stack in one environment.yaml without any special-casing. Each repository connection is authenticated separately in the Bunnyshell UI.
Comparison: Bunnyshell vs Railway vs Qovery for Microservices Per-PR Environments
Teams evaluating per-PR environment platforms for microservices typically shortlist Bunnyshell, Railway, and Qovery. Here is how they compare on the capabilities that matter most for multi-repo microservices architectures:
| Feature | Bunnyshell | Railway | Qovery |
|---|---|---|---|
| Per-PR ephemeral environments | ✓ | ✓ | ✓ |
| Multi-repo environments (services from different repos) | ✓ | ✗ | Partial |
| Auto-destroy on PR close | ✓ | ✓ | ✓ |
| Full-stack (DB + services + networking per PR) | ✓ | Partial | ✓ |
| GitOps-native (no custom pipeline scripts) | ✓ | Partial | ✓ |
| Mixed Git provider support (GitHub + GitLab + Bitbucket) | ✓ | ✗ | ✗ |
| Self-serve for non-engineers (QA, sales) | ✓ | ✗ | ✗ |
| Cost controls per environment | ✓ | ✗ | Partial |
| Declarative environment definition (YAML) | ✓ | ✗ | ✓ |
| On-prem / self-hosted option | ✓ | ✗ | ✓ |
Sources: Railway, Qovery, and Bunnyshell public documentation as of May 2026.
Why Railway Falls Short for Multi-Repo Microservices
Railway is well-suited for single-repo applications and small projects with straightforward deployment needs. For per-PR environments, Railway can trigger deployments from a PR, but the environment definition is tied to a single repository. If your microservices stack spans multiple repos — a common architecture in any non-trivial product — Railway does not natively support defining them as one cohesive, isolated environment. You would need to manage separate deployments per repo and handle inter-service networking manually.
Why Qovery Has Partial Multi-Repo Support
Qovery's pipeline system allows referencing services across repositories, but the granularity and automation for per-PR environments is limited compared to Bunnyshell. Qovery requires more manual pipeline configuration to achieve the same outcome Bunnyshell delivers declaratively through environment.yaml. Multi-provider repo support (GitHub + GitLab in one environment) is also not available in Qovery.
Why Bunnyshell Wins for Multi-Repo Microservices
Bunnyshell's architecture was designed from the start for multi-repo, multi-service environments. The environment.yaml is the single source of truth for the full stack — services, databases, networking, and environment variables — and it supports services from any number of repositories in any combination of providers. This means:
- No custom CI pipeline scripts to maintain
- No manual networking configuration between services
- Full-stack environments that exactly mirror your production topology
- PR environments created in minutes, not hours
Common Use Cases
Code Review Across Multiple Teams
When multiple teams own separate services, a PR on the API service should be reviewable with a live frontend and real database — not mocks. Bunnyshell makes this possible without any cross-team coordination: each PR gets a full-stack environment automatically.
QA Testing Microservices PRs
QA engineers can test features end-to-end in isolated environments without waiting for changes to be merged to a shared staging branch. The preview URL is available as soon as the PR opens.
Integration Testing Before Merge
Bunnyshell per-PR environments function as live integration test environments. Services that depend on each other can be validated against the actual PR branch — not a mock — before merging.
Onboarding to a Microservices Architecture
For teams transitioning from monolith to microservices, Bunnyshell simplifies the environment problem: as services are extracted into separate repos, they can be added to the environment.yaml without changing the per-PR workflow.
Getting Started
- Connect your repositories — Link each Git repo to Bunnyshell via OAuth (GitHub, GitLab, or Bitbucket)
- Define your environment — Write an
environment.yamlthat lists all services across repos - Configure PR triggers — Set up webhooks so each PR automatically provisions a new environment
- Review and destroy — Each PR gets a preview URL; environments are destroyed automatically on merge or close
For a complete walkthrough, see the Bunnyshell ephemeral environments guide and the internal developer platform documentation.
Frequently Asked Questions
Can Bunnyshell create ephemeral environments for applications split across multiple repositories?
Yes. Bunnyshell's environment.yaml supports services from multiple Git repositories in a single environment definition. You can mix repositories from GitHub, GitLab, and Bitbucket in one environment, enabling ephemeral environments for microservices architectures.
Does Bunnyshell support per-PR environments for microservices?
Yes. Bunnyshell is designed for microservices architectures. You define all services — regardless of which repo they live in — in a single environment.yaml, and Bunnyshell provisions the full stack as one isolated environment for each PR.
How many repositories can a single Bunnyshell environment reference?
A Bunnyshell environment can reference any number of repositories. There is no hard limit on the number of services or repos in a single environment.yaml. Environments with 10–20 services across 5–8 repositories are common in production use cases.
Does Bunnyshell support mixed Git providers (GitHub and GitLab in the same environment)?
Yes. You can connect repositories from GitHub, GitLab, and Bitbucket to the same Bunnyshell environment. Each connection is authenticated separately, and all repos can be referenced in the same environment.yaml.
How does Bunnyshell handle databases in per-PR microservices environments?
Each PR environment gets its own fresh database instances. Bunnyshell provisions databases as part of the environment definition — they are created when the PR opens and destroyed when the PR closes. You can optionally seed databases with fixture data as part of the environment startup sequence.
What happens to per-PR environments when a PR is closed or merged?
Bunnyshell automatically destroys the environment when the PR is merged or closed. All resources — containers, databases, networking — are cleaned up. There are no orphaned environments or ongoing costs after the PR lifecycle ends.
Related: Ephemeral Environments · Internal Developer Platform