Services of a project: web services, workers and scheduled jobs.
Add background workers, scheduled jobs, more web services, databases and Valkey to a project — from its own code, another repository or a ready image — reachable by name and on one bill.
A project is more than one process. Next to the main application you can run a queue worker, a nightly job, a separate API, a database — each as a service with its own resources, all on one bill.
Services are listed on the application's Overview → Services → Add a service. A project can have up to 10 services. The main service must be launched first, and the project's subscription must be active (the trial counts).
Kinds of services
| Kind | What it is |
|---|---|
| Web service | another site or API — with a public address or internal only |
| Background worker | runs all the time: queues, Horizon, Celery, consumers |
| Scheduled job | starts on a schedule (cron format, UTC), does its work and stops |
| PostgreSQL, MySQL, Valkey | managed databases — see Databases |
| NATS, RabbitMQ | message brokers for events and queues, internal only — see Events and queues |
Public address or internal only
When you add a web service, choose how it can be reached — nothing is selected in advance:
- Public address — open from the internet at
https://<name>.rivervo.app; it can have your own domains. - Internal only — no address on the internet and no domains; only the other services of the application reach it. Right for an API behind your site, an admin backend or a search engine.
Background workers, scheduled jobs and databases are never public, so there is no choice for them. You can change it later in the service's Settings → Public address — see Service-to-service communication.
Where the code comes from
This project's code
The same code started another way: a queue worker, a scheduler, a WebSocket server (for example Laravel Reverb), a folder of a monorepo, a separate API.
- Command is required — what the service runs, e.g.
php artisan queue:workornode worker.js. - A web service must listen on the port in
$PORT. - A scheduled job also needs a Schedule in cron format (UTC), e.g.
*/5 * * * *. - Every new version of the main service is deployed to these services too, so they always run the same code.
Another repository
A web service or a background worker from a different repository of your connected Git account, with its own branch and, if needed, Project folder and Build and start commands (leave a field empty to use what we detect). It gets its own deploys and versions and deploys every push to its branch. Branch previews are not made for services yet.
A ready image
A web service or a background worker from a ready image (Docker image) on Docker Hub, GitHub Container Registry or any other registry — for example nginx:1.27 or ghcr.io/org/app:tag.
- Port — the port the image listens on; we also pass it in
$PORT. - Command — optional; empty starts the image as it is built to.
- Private registry — a user name and a password or access token. They are stored encrypted, used only to download the image and never shown again.
- With automatic deploys on, we check once a day whether the tag points to a newer version and deploy it. Download the image again on the Deploys tab does it right away.
Kafka (template)
Kafka in Add a service is a one-click preset: it creates a service from the official Apache Kafka image (3.9) — a single broker in KRaft mode, without ZooKeeper. It suits development and moderate loads.
- Internal only — no public address and no access from outside; only the application's services reach it.
- The application's other code services get
KAFKA_BROKERS=<service name>:9092andRIVERVO_<NAME>_URL=<service name>:9092. - Topics are created automatically the first time they are used.
- It starts with 1 GB of memory · 1 CPU core · 10 GB of disk. Like any service from a ready image, you can change its resources and variables.
- Its data is kept in the service's data folder on its disk.
What it does not have:
- One broker — no replication; every topic has a replication factor of 1.
- No managed Kafka backups. The daily backup copies its data folder as files while Kafka runs. That is not a consistent Kafka backup: after a restore recent messages may be missing, or Kafka may need to recover its logs when it starts.
- No maintenance time, no access from outside and no Kafka UI.
- Upgrading Kafka is up to you: change the image in the service's Settings.
For queues and events with backups and connection variables set up for you, see Events and queues — NATS and RabbitMQ.
Reaching each other by name
Services of a project talk over a private network by name: a service called api is reachable from the others as api, a database called db as db, and the main service as web. Traffic between services of a project is not counted as traffic.
Every web service shows its Internal address — for example http://api:8080 — and the other services get it in a variable, RIVERVO_API_URL. How it works, internal-only services, several instances and timeouts: Service-to-service communication.
Every service gets the project's variables — including the database connection — plus variables of its own, which win over the project's. See Environment variables.
Resources and price
Each service has its own Memory, CPU and Disk, priced like any application: $6 per GB of memory and $4 per CPU core a month, with 10 GB of disk included per GB of memory, then $0.15 per GB. A service can have up to 8 GB of memory.
When you add a service, its price is added to the project's bill — for the current month only the remaining part of it. While the project is on its free trial, new services are free until the trial ends.
The Overview shows Project total — what all services of the project cost a month together.
Workers inside the application itself
You don't always need a separate service. The main application's Processes tab has:
- Background workers — up to 5 long-running processes next to the site, e.g. a queue worker. They share the application's resources and restart with every deploy.
- Scheduled commands — up to 10 commands on a schedule (cron format, UTC). Their output is in the log under Schedule.
- Console — run a one-off command inside the running application, with its variables and database. A command can run up to 15 minutes; interactive commands (tinker, a shell) are not supported here.
A separate service is the better choice when a worker needs its own resources, so that a heavy queue never slows the site down.
Changing a service
Open the service from the Services list. Its Settings hold the command, schedule, image or branch, and its resources; changes are saved and the service restarts with them. Each service also has its own Logs and Monitoring.