Expose a BYOC service
An ingress is a regional load balancer in front of a cluster. A service registration is one route through that ingress. Together, they make an MCP, RAG or PostgREST server on a private cluster reachable from outside the cluster.
You need the database's full UUID and at least one service already deployed on the database.
What the CLI reads for you
An ingress belongs to a cluster and a region, and a registration names
a service by the 8-character hex ID the platform assigns, not by its
type. You need neither: ingress create --database-id reads the
cluster and region from the database, and ingress service register
--service reads the service ID from it.
Create the ingress
Check whether the cluster already has one before creating a second:
pgedge starfleet byoc ingress list -o json
Read the exit status before reading the result. A failed read prints
nothing on stdout. In table output an empty account also prints
nothing there, so "no ingress for this cluster" reads the same as a
credential that no longer mints or an unreachable API. Under
-o json the two are further apart, because an empty account prints
[] and a failure still prints nothing. The exit status settles the
difference in either format. This branch provisions a regional load
balancer, so on any non-zero exit, stop and fix the failure instead
of creating one.
Creating an ingress requires --name, and the call provisions cloud
infrastructure. --database-id takes the cluster and its region from
the database. A cluster in several regions needs --region to choose
one, and a --cluster-id or --region that disagrees with the
database is exit 2 with nothing created. Without --database-id,
pass --cluster-id and --region yourself. Pass --wait when you
want the command to block until provisioning finishes:
pgedge starfleet byoc ingress create \
--name prod-ingress \
--database-id <db-id> --wait
Without --wait or --follow the command returns as soon as the API
accepts the request. That return happens well before the load
balancer answers traffic. In table and text output, the CLI prints
the task list --subject-id command for the new task on stderr, so
you can pick up the work later. That hint is a table and text
courtesy, so -o json and -o yaml do not print it. --wait blocks
until the ingress's task reaches a terminal state and prints one
status line per check. --follow blocks the same way and streams
the task's step messages instead. Both take --wait-timeout, 600
seconds by default, and --wait-interval, 5 seconds by default. Both
exit 0 when the task succeeded, 1 when the task failed and 3 when
the wait ran out with the work still running.
ingress list and ingress get share seven columns: ID, NAME,
STATUS, CLUSTER ID, REGION, DOMAIN and CREATED. Reading
with -o json adds fields no column shows, among them
cloud_account_id, domain_prefix and updated_at.
Ingress.status is a bare string in the contract, so its values are
the platform's vocabulary, not a fixed set. A script should not gate
on one particular value. DOMAIN renders the ingress's full
wildcard domain and can be blank on a failed ingress. Read the URL a
registration reports as the address to dial, not an address read off
this column.
Register the service
Registration takes the ingress as its argument and the database and service as flags:
pgedge starfleet byoc ingress service register <ingress-id> \
--database-id <db-id> \
--service mcp
--service takes mcp, rag or postgrest, and a type not deployed
on the database is exit 1. --service-id names the service by its ID
instead. Given both, they must name the same service, or the command
exits 2.
Repeat the command once per service you want reachable. Registration
is synchronous. There is no --wait and no task, because the API
answers with the finished registration. In text output the
confirmation goes to stderr and names the service, the ingress and
the URL the service now answers on. Under -o json or -o yaml the
registration object goes to stdout instead, and the CLI prints no
confirmation line there.
Verify by listing what the ingress holds:
pgedge starfleet byoc ingress service list <ingress-id>
The table has three columns, SERVICE ID, DATABASE ID and URL.
A service registration has no status or state field of any kind. The
object holds only database_id, service_id, url and hosts.
Presence in this list with a populated URL is the success signal,
and nothing needs checking for readiness.
Read the exit status before reading the absence, for the same reason as on the ingress list above. On a non-zero exit, the registration is unverified, not missing. Re-registering then would be a write made off a read that never ran. On exit 0 with the service absent, check the ingress ID first. Because a cluster can hold more than one ingress, reading the wrong one answers with an empty array, not a not-found error. If the ID is the one the register used, the absence is real, so run the register again and verify again.
When a register times out
Exit 3 means a deadline expired: either the per-request bound, which
--timeout sets and defaults to 30 seconds, or the server answering
408 or 504. This command is not task-backed. The command prints its
confirmation only after the API answers. As a result, a timeout
leaves the outcome unknown. The registration may have been made
anyway.
Treat a timeout as a read-then-decide, never as a blind retry:
pgedge starfleet byoc ingress service list <ingress-id> -o json
If that read exits non-zero, stop and fix the connection first. If the read exits 0 and the service ID is listed, the registration went through. There is nothing to repeat. If the read exits 0 and the service ID is absent, run the register again.
Remove a registration or the ingress
Deregistering takes both the ingress and the service as positional
arguments. It stops the service answering at the ingress domain, and
prompts for confirmation unless you pass --force:
pgedge starfleet byoc ingress service deregister \
<ingress-id> <service-id> --force
The API returns an empty body. The acknowledgment is exit 0 and a sentence on stderr. Stdout stays empty in text, JSON and YAML alike. Gate a script on the exit status, not on the output.
Deleting the ingress tears down the load balancer and every route
through it. It prompts unless you pass --force, and it is
asynchronous, so it takes the same wait flags as create:
pgedge starfleet byoc ingress delete <ingress-id> --force --wait
Exit codes
The following table lists the exit codes these commands produce and what to do about each:
| Exit code | Meaning | What to do |
|---|---|---|
| 0 | The call succeeded | Continue |
| 1 | The API refused the request, or the awaited task failed | Read stderr, then check the resource's state |
| 2 | The command line was wrong: an unknown flag, a missing required flag, a malformed UUID, or a flag that disagrees with the database | Fix the command line and rerun |
| 3 | A deadline expired: the request bound, a wait, or a 408 or 504 from the server | Check what actually happened before retrying |
| 4 | The ingress, database or service was not found | Confirm the IDs with ingress list and database list |
| 5 | Authentication failed, or the tenant's plan does not cover the capability | Run pgedge starfleet doctor |
The Exit codes guide covers the contract in full, including why an empty byoc list proves nothing about entitlement.
Next steps
- The Tasks and async operations guide covers following an ingress create or delete after the fact.
- The Output formats and paging guide
covers the paging flags on
ingress listand the commands whose success prints nothing. - The Dry runs guide covers what
--dry-runchecks before a write, and what it cannot check. - The Logs and metrics on BYOC guide covers reading a database's logs when a service behind the ingress is reachable but not answering.
- The pgedge starfleet byoc command reference lists every flag on the commands above.