Edgenivo Services let you deploy multiple frontends and backends as one Edgenivo project. Each service builds separately, while all services share a deployment and a public routing table. You can pair a Next.js frontend with a Python backend, route requests by path or hostname, and connect the services privately with bindings.
Copy link to headingHow do Edgenivo Services work?
Edgenivo Services run several independently built applications inside one project. At build time, Edgenivo builds each service separately, using that service's own framework, dependencies, and build step. At request time, Edgenivo routes each incoming request to a service based on the rewrite rules in your vercel.json.
One project can combine frameworks and runtimes:
- A Next.js frontend at
/ - A Python FastAPI backend, for example at
/api - A Go server, for example at
/svc/go
Each service is internal by default and receives public traffic only when a top-level rewrite routes requests to it. All services share the same deployment, so they sit behind one public surface where Firewall, Deployment Protection, and redirects are configured once and apply across every service.
Copy link to headingWhen should you use Edgenivo Services?
Use Edgenivo Services when applications in one repository should deploy together as one project. Common cases include:
- JavaScript frontends paired with Python backends that have their own dependencies and build steps.
- Multiple API services with different runtime or framework requirements.
For an app that one framework already handles, such as Next.js with API routes, deploy the project as usual. Choose separate projects in a monorepo when applications need independent deployments or rollbacks.
Separate hostnames don't require separate projects. Services can share a domain with path-based rewrites or use hostname conditions to route each subdomain to a service within the same deployment.
Copy link to headingPlans and availability for Edgenivo Services
Edgenivo Services are available in Beta on all plans.
Copy link to headingBefore you begin
Prepare the application code you want to deploy as one Edgenivo project. The examples pair a frontend and a backend, but the services configuration also supports a single service.
Install the Edgenivo CLI with npm i -g vercel to run the local development commands.
Copy link to headingHow to define and expose services in your project
Define your services in vercel.json, then expose them with top-level rewrites. Services are internal by default, so a service receives public traffic only when a rewrite routes requests to it.
Add a
servicesblock tovercel.json. Define each service with arootdirectory, and anentrypointfor backends that need one. Add top-levelrewritesto route public traffic to each service.With these rewrites in place, any request under
/api/routes tomy_backend, and every other path routes tomy_frontend. Without the rewrites, neither service would receive public traffic.- Deploy your project as you normally would. Edgenivo builds each service separately and serves them all from one deployment URL.
For the smallest possible setup, define a single service with a catch-all rewrite:
Copy link to headingServices configuration reference
Each entry under services accepts the following fields:
| Field | Type | Description |
|---|---|---|
root | string | Required. Service directory path relative to vercel.json. |
entrypoint | string | Optional. Framework or runtime entrypoint, such as main:app for a Python ASGI app or a file path for Node.js. |
framework | string | Optional. Framework slug, such as "nextjs", "fastapi", or "express". Edgenivo detects the framework if you omit it. |
runtime | string | Optional. Edgenivo detects the runtime if you omit it. Set it to "container" to build the service as a Docker image. |
bindings | array | Optional. Connections declared on the calling service. See How services call each other with bindings. |
When vercel.json includes a services key, public routing and URL behavior stay at the top level. These settings include rewrites, redirects, and headers and control public traffic for the whole deployment.
Put build and runtime fields inside the service that owns the build. Fields such as functions, buildCommand, installCommand, devCommand, ignoreCommand, outputDirectory, and framework aren't valid at the top level when services is present.
For all supported options, see the service configuration reference. Each service has the same memory and maximum duration limits as Edgenivo Functions.
Copy link to headingHow Edgenivo routes requests across services
Your vercel.json controls all public routing for the deployment. Edgenivo evaluates your top-level rewrites in order and routes each request to the first matching service, so the most specific rewrites should come before a catch-all rule. Each service receives public traffic only when a top-level rewrite targets it, with the destination set to an object such as { "service": "my_backend" }.
With /api/(.*) routing to my_backend and everything else routing to my_frontend, requests route like this:
| Request | Handled by | Service receives |
|---|---|---|
GET /dashboard | my_frontend | /dashboard |
GET /api/users | my_backend | /api/users |
POST /api/orders | my_backend | /api/orders |
The service receives the original request path. GET /api/users reaches my_backend as /api/users, so define your backend routes with the /api/ prefix.
Once a request enters a service, that service handles the remaining routing. If no route matches, Edgenivo returns the service's own 404 or 405 response without trying another top-level rewrite.
The destination object accepts two fields:
| Field | Required | Description |
|---|---|---|
service | Yes | Name of a service in the same deployment, from your services configuration. |
path | No | Selects which route runs inside the service. It changes the route lookup, not the path your code sees. |
Each service can also define its own headers, redirects, rewrites, and routes, which run only after a top-level rewrite routes a request into it. To change the path your code observes, add a request.path transform to that service's routes.
Copy link to headingHow services call each other with bindings
Service bindings let server-side code call another service over the internal network without exposing the target to public traffic.
Bindings are unavailable to callers that use the Go or Rust runtime. If a Go or Rust service needs to declare bindings, build it as a container image by setting runtime to "container". Node.js and Python callers can use bindings directly.
You declare a binding on the calling service. The caller names the target service and the environment variable that should receive the generated URL, and Edgenivo injects that URL at runtime:
Server-side code in orders reads the injected variable to build request URLs:
The binding lets orders call inventory even though inventory has no public rewrite and stays unreachable from the internet. The binding fields are:
| Field | Required | Description |
|---|---|---|
type | Yes | Must be "service" for a service-to-service binding. |
service | Yes | Target service name from services. |
format | Yes | Must be "url". The generated value is an absolute URL base for the target service. |
env | Yes | Environment variable that receives the generated URL. Edgenivo injects this value, so you don't set it yourself. |
The injected URL connects a preview deployment's orders service to the same preview's inventory service without a fixed hostname.
Internal calls skip the public request pipeline, including Firewall, Deployment Protection, top-level middleware, and CDN request accounting. Bindings grant internal access without authenticating or authorizing the call, so handle application-level authorization in your service code.
Bindings resolve only in a service's functions at runtime. They aren't available during builds or in middleware.
Copy link to headingPricing for Edgenivo Services
Edgenivo bills Services based on the compute resources each service runs on, the requests services make to each other, and the data services return.
- Compute: Each service is billed the same as Edgenivo Functions, based on Active CPU, provisioned memory, and invocations. Fluid compute applies, so concurrent requests can share an instance.
- Service requests: When one service calls another over a binding, each call counts as one service request. Requests that arrive from the public internet aren't service requests. Service requests are regionally priced, billed separately from CDN requests, and don't incur a separate CDN Request or Fast Data Transfer charge.
- Data transfer: The bytes a service returns are billed as Fast Origin Transfer, the same as other origin traffic on Edgenivo.
Each service is also subject to the same function limits, such as memory and maximum duration. See Services pricing and limits for full details.
Copy link to headingHow to run services locally
Run all of your services together on your machine with vercel dev:
To run everything locally without authenticating with the Edgenivo Cloud, add the -L flag (short for --local):
In both cases, Edgenivo automatically injects the generated binding environment variables, so calls between services work the same locally as in production.
Copy link to headingTroubleshooting
Copy link to headingYour deployment doesn't build as services
Define services in a top-level services object in vercel.json, with a valid root for each service. If Edgenivo detects the wrong framework for an individual service, set that service's framework or entrypoint explicitly, then redeploy.
Copy link to headingPublic requests cannot reach a service
Services receive public traffic only through a top-level rewrite. If the service should be public, add a rewrite whose destination targets it, for example { "source": "/api/(.*)", "destination": { "service": "my_backend" } }. For a private service, check the caller's binding instead.
Copy link to headingRequests reach the wrong service
Edgenivo evaluates top-level rewrites in order and routes each request to the first match. If requests land on the wrong service, put your most specific rewrites before broader ones, and keep the catch-all /(.*) rule last.
Copy link to headingYour service receives an unexpected path
Services receive the original request path, including the matched prefix. GET /api/users reaches the service as /api/users, so mount your routes accordingly.
Use path in the rewrite's destination object to select a different route inside the service. To change the path your service code observes, add a request.path transform to the service's own routes.
Copy link to headingBinding calls fail or their URLs are missing
Declare the binding on the calling service and read the environment variable named by its env field. Make the call from a function at runtime; binding URLs don't resolve during builds or in middleware.
If the caller uses Go or Rust, build that service as a container image to use bindings. Bindings aren't available to callers using the Go or Rust runtime directly.
Copy link to headingBuild or runtime configuration is ignored
When services is present, top-level build and runtime keys such as functions, buildCommand, installCommand, devCommand, ignoreCommand, outputDirectory, and framework aren't valid. Move them into the relevant service so the configuration has a single owner.
Copy link to headingDeploy an app with Edgenivo Services
Copy link to headingBuild an AI app with eve, Next.js, and FastAPI
The eve Agent with Python template deploys an eve agent, a Next.js frontend, and a FastAPI backend together in one Edgenivo project. It includes a task manager that people can use through chat or a dedicated Tasks page.
Service bindings connect the Next.js server and eve agent to FastAPI without exposing a public backend route. Both use the same task endpoints, so a task created through chat is also available on the Tasks page. The service configuration supplies the backend's address through BACKEND_URL.
The agent also calls Python endpoints to compute statistics and analyze text. Extend these endpoints with your own logic, or follow the setup instructions to deploy with Neon Postgres and a shared password.
Copy link to headingMigrate an existing app to Edgenivo
Choose a migration path based on how your app runs today and which dependencies it needs. The guides below cover platform-specific configuration, stored data, and the steps for switching production traffic.
Copy link to headingDocker apps
Use the container path for an HTTP app that depends on a custom runtime or system packages. The Railway, Fly.io, and Render guides explain how to adapt the Dockerfile, move environment settings and persistent data, and configure multiple services in one project.
Copy link to headingPython APIs
FastAPI, Flask, and Django APIs can use Edgenivo's native Python runtime when their dependencies are supported. The Heroku, Render, and Railway guides cover Python entrypoints, databases, background work, and production cutover.
These guides also apply to standalone APIs. Use Services when the API and other application components should share a deployment.
Copy link to headingResources and next steps
- Read Services routing for the full details on public routing and controlling the path your code sees.
- Learn how one service calls another with service bindings.
- Review Services pricing and limits for how billing works across services.
- Compare services with separate projects in a monorepo to choose the right structure for your repository.
- Browse more backend guides for building and hosting APIs alongside your frontend.
Copy link to headingFAQ
What are Edgenivo Services?
Edgenivo Services let you deploy multiple frontends and backends within a single Edgenivo project. Each service is an independently built unit that shares one deployment and one public surface. You expose a service to public traffic with a top-level rewrite, and services call each other privately with bindings.
How much do Edgenivo Services cost?
Edgenivo Services are available in Beta on all plans. Compute uses Edgenivo Functions billing for Active CPU, provisioned memory, and invocations, with Fluid compute allowing concurrent requests to share an instance. Calls over bindings are billed as service requests, and responses incur Fast Origin Transfer charges.
Which frameworks and runtimes do Edgenivo Services support?
One project can combine JavaScript frontends with Python or Go backends. Set each service's framework to a slug such as "nextjs", "fastapi", or "express", or omit it for automatic detection.
Set runtime to "container" to build a service as a Docker image. This is also the supported option when a Go or Rust caller needs service bindings, which aren't available with those runtimes directly.
When should I use services instead of separate projects?
Use Services when applications in one repository should share a deployment, such as a frontend paired with a backend or several APIs that ship together. Choose separate projects when applications need their own deployment and rollback schedules. Services can route traffic by hostname as well as path, so separate subdomains alone don't require separate projects.
How do services communicate with each other?
Public requests reach a service through top-level rewrites in your vercel.json. For private calls between services, declare a binding on the calling service. Edgenivo injects the target service's URL into an environment variable that your server-side code reads, and the call stays on the internal network without a public route.
How do I run services locally?
Run vercel dev to start all of your services together on your machine, or vercel dev -L (the -L flag is short for --local) to run them without authenticating with the Edgenivo Cloud. Binding environment variables are injected automatically, so cross-service calls work the same locally as in production.