• Docs
  • Changelog
Sign in
Get started
    • Home
    • Your first deploy
    • Free instances
    • Platform features by plan
    • Use with coding agents
    • FAQ
    • Templates
      • Migrate from…
        • Heroku
        • Railway
    • Compute plans
    • SandboxesBeta
      • Service types
        • Which to use?
        • Static sites
        • Web services
        • Private services
        • Background workers
        • Cron jobs
        • Workflows
        • Multi-service architectures
      • Data storage
        • Render Postgres
        • Render Key Value (Redis®-compatible)
        • Persistent disks
    • How deploys work
    • Supported languages
    • Git providers (GitHub, etc.)
    • Build pipeline
    • Deploy hooks
    • Monorepo support
    • Troubleshooting deploys
      • Previewing changes
        • Single-service previews
        • Preview environments (multi-service)
      • Docker deploys
        • Overview
        • Deploy a registered image
        • Using secrets
      • Runtime
        • Native runtimes
        • Environment variables & secrets
        • Default environment variables
    • Intro to sandboxes
    • Limits
      • How to…
        • Create & configure sandboxes
        • Execute commands
        • Manage files
        • Manage snapshots
      • Use with…
        • Claude Managed Agents
        • Cursor Cloud Agents
        • OpenAI Agents API
      • SDK/CLI reference
        • TypeScript SDK
        • Python SDK
        • CLI commands
    • Intro to workflows
    • Tutorial
    • Limits & pricing
      • How to…
        • Define tasks
        • Define flowsNew
        • Trigger runs
        • Develop locally
      • SDK reference
        • TypeScript SDK
        • Python SDK
      • Example workflows
        • TypeScript examples
        • Python examples
    • Overview
    • Create & connect
    • Database credentials
    • Extensions
    • Version upgrades
    • Logical replication
    • Legacy instance types
      • Database recovery
        • Recovery & backups
        • High availability
      • Database performance
        • Read replicas
        • Connection pooling
        • Admin apps
        • Repacking tables
        • Troubleshooting performance
    • Regions
    • Inbound IP rules
    • Edge caching
    • WebSockets
    • TLS certificates
      • Custom domains
        • Overview
        • Cloudflare
        • Namecheap
        • Other DNS providers
      • Internal traffic
        • Private network
        • Private links
      • Outbound traffic
        • Default IP ranges
        • Dedicated IP addresses
        • Outbound bandwidth
        • Handling network changes
      • Static site config
        • Custom response headers
        • Redirects & rewrites
    • The Render Dashboard
    • SSH / Shell access
    • Projects & environments
      • Service actions
        • Scaling
        • Rollbacks
        • Maintenance mode
        • One-off jobs
      • Infrastructure as code
        • Blueprints overview
        • render.yaml reference
        • Terraform provider
    • In-dashboard metrics
    • Health checks
    • Uptime best practices
      • Logging
        • In-dashboard logs
        • Log streams (syslog/HTTPS)
      • OpenTelemetry (OTel) metrics
        • Provider setup
        • Metrics reference
      • Notifications
        • Webhooks
        • Email / Slack
    • MCP Server
      • Render CLI
        • Overview
        • Command reference
      • REST API
        • Overview
        • API reference
      • Third-party connections
        • OIDC support
        • Datadog
    • Workspaces, members, & roles
    • Login settings
    • Audit logs
      • Organizations
        • Overview
        • SAML SSO
    • DDoS protection
    • Platform maintenance
      • Compliance
        • Overview
        • HIPAA (US health data)
        • HIPAA best practices
        • Shared responsibility model
        • Pentest policy
    • Heroku vs Render
    • Vercel vs Render

Multi-Service Architectures on Render

This guide teaches you how to:

  • Combine different Render service types into a common web app architecture
  • Set up connections between services using environment variables
  • Communicate between services over a private network

Modern cloud applications usually consist of multiple connected services:

A multi-service architecture like this one enables you to deploy, scale, and even swap out individual parts of your app—all with minimal impact on the rest of your system.

The Render platform is designed from the ground up to support multi-service architectures. You can assemble different service types into any combination you need, using any set of languages and frameworks.

Let's look at an example.

Example scenario

A common multi-service web app might consist of:

  • A React or Next.js website for the app's frontend
  • An Express or Django API server to handle requests from clients
  • A relational database for long-term storage of application data

We can represent each of these components as a separate service on Render:

ComponentService TypeCommon Frameworks
FrontendStatic site (or a web service if the frontend includes server-side logic)React, Next.js, Vue.js
BackendWeb serviceDjango, Express, FastAPI
DatabaseRender Postgres database

Let's walk through deploying an app with these components. You can apply these steps to your own app, regardless of which frameworks you use.

Prerequisites

Before we start deploying, confirm all of the following:

  1. You've created your Render account.
  2. Each project you want to deploy is one of the following:
    • A repository hosted on a Git provider
    • A Docker image in a supported registry, such as Docker Hub
  3. Your full application works as expected on your local machine.
  4. You've consulted your chosen framework's documentation for specific deployment guidance.
    • For example, here's the deployment guide for Next.js.

Steps to deploy

In the steps below, we'll first deploy each component of our architecture. Then, we'll connect them by setting environment variables.

1. Create a database

Render provides fully managed PostgreSQL databases with point-in-time recovery, along with reliability features like read replicas and high availability for larger instances.

We can create a Render Postgres database with a few clicks in the Render Dashboard:

Creating a new Postgres database in the Render Dashboard

Follow these steps, then return here.

2. Deploy the backend

Our application's backend will handle incoming HTTP requests from browsers and other clients. To support this, we'll create a web service.

Web services receive a public onrender.com URL, and you can add your own custom domains. You can use virtually any web framework for your web service (Django, Express, FastAPI, and so on).

To deploy a backend that only receives traffic from your own Render infrastructure, create a private service instead.

  1. Make sure that on startup, your backend code binds an HTTP server to a port on host 0.0.0.0.

    • We recommend binding to the value of the PORT environment variable (default 10000).

    • If you're building from a Dockerfile, indicate your HTTP port in the file like so:

      Learn more about the EXPOSE instruction.

  2. Create a new web service in the same region as your database and deploy your backend code to it.

    • Follow these steps, then return here.

3. Deploy the frontend

Our application's frontend will serve the content that users view and interact with in their browser.

Depending on our frontend's framework, we'll deploy our code as either a static site or a second web service:

Service typeWhen to useExample frameworks
Static siteFor apps with entirely static content (HTML/CSS/JS)

React, Vue.js, Next.js (static exports only)

Web serviceFor apps with server-side logicNext.js, Nuxt.js

Render static sites are served by a globally distributed CDN, so we recommend using them for any framework that supports it.

To deploy your frontend, follow the instructions for your chosen service type, then return here:

  • Static site
  • Web service

4. Connect your services

After creating and deploying our services, we need to configure them to communicate with each other. To do this, we can set environment variables on a service to specify the address of each other service it connects to:

Let's set up connections for our frontend and backend services.

Update the frontend service

  1. Look up the public URL of your backend service.

  2. Add an environment variable to your frontend service:

    • Give the environment variable a helpful name (such as BACKEND_URL) and set its value to your backend's public URL.
    • For static site frameworks, you might need to use a specific name for the environment variable (such as REACT_APP_BACKEND_URL for React).
  3. Update your frontend code to use the new environment variable to connect to your backend. For example, in JavaScript:

  4. Push your updated code to your linked branch to deploy your changes.

Update the backend service

  1. Look up the public URL of your frontend service.

  2. Look up the internal address of your Render Postgres database.

    • Backend services on Render can communicate with each other using their "internal" (or "private") addresses. When you use an internal address, traffic between the services stays on their private network—it doesn’t traverse the open internet.
  3. Add environment variables to your backend service:

    • Define a FRONTEND_URL variable and set its value to the frontend's public URL.
    • Define a DATABASE_URL variable and set its value to the database's internal address.
  4. Update your backend code to use the FRONTEND_URL and DATABASE_URL environment variables to connect. See examples below.

    • Using FRONTEND_URL to set CORS headers in Express middleware:

    • Using DATABASE_URL to connect to a database with the pg Node.js library:

  5. Push your updated code to your linked branch to deploy your changes.

After your frontend and backend deploys complete, your app should be up and running! Visit your frontend URL to confirm. If you encounter any issues, see Troubleshooting Deploys.

Consider infrastructure as code (IaC)

As your architecture grows in scale, it becomes more and more helpful to manage your services in a unified way. Render Blueprints enable you to configure and update the entire architecture of your app with a single YAML file.

Show example Blueprint

You can even generate a Blueprint for your existing services, which makes it much faster to get started.

Multi-Service Architectures on Render
  • Example scenario
  • Prerequisites
  • Steps to deploy
    • 1. Create a database
    • 2. Deploy the backend
    • 3. Deploy the frontend
    • 4. Connect your services
  • Consider infrastructure as code (IaC)
Partially Degraded Service
© Render Inc. All rights reserved.