-
Notifications
You must be signed in to change notification settings - Fork 2
feat: first pass at service docs. #315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # Supporting Services (Beta) | ||
|
|
||
| The pgEdge Control Plane lets you run services alongside your | ||
| databases. Services are applications that attach to a database, run on | ||
| any host in the cluster, and connect via automatically-managed | ||
| database credentials. | ||
|
|
||
| ## What Are Supporting Services? | ||
|
|
||
| A supporting service is an application that runs alongside a database. | ||
| Each service instance runs on a single host and receives its own set of | ||
| database credentials scoped to that instance. The Control Plane supports | ||
| the following service types: | ||
|
|
||
| - The [pgEdge Postgres MCP Server](mcp.md) connects AI agents and | ||
| LLM-powered applications to your database, enabling natural language | ||
| queries and AI-powered data access. | ||
| - The pgEdge RAG Server *(coming soon)* enables retrieval-augmented | ||
| generation workflows using your database as a knowledge store. | ||
| - PostgREST *(coming soon)* automatically generates a REST API from | ||
| your PostgreSQL schema, making your data accessible over HTTP without | ||
| writing backend code. | ||
|
|
||
| ## Service Instances | ||
rshoemaker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| When you add a service to a database, the Control Plane creates one | ||
| service instance per host listed in the service's `host_ids`. Each | ||
| instance runs on a single host and receives its own database | ||
| credentials. Services can run on any host in the cluster; they do not | ||
| need to be co-located with database instances. | ||
|
|
||
| The following table describes the lifecycle states for service | ||
| instances: | ||
|
|
||
| | State | Description | | ||
| |-------|-------------| | ||
| | `creating` | The Control Plane is provisioning the service instance. | | ||
| | `running` | The service instance is healthy and operational. | | ||
| | `failed` | The service instance exited or failed its health check. | | ||
| | `deleting` | The Control Plane is removing the service instance. | | ||
|
|
||
| ## Deployment Topologies | ||
|
|
||
| Services are independent of your database node topology, so you can | ||
| place service instances on any host in the cluster. The following | ||
| deployment patterns are common: | ||
|
|
||
| - In a co-located topology, the service runs on the same host as a | ||
| database instance, which minimizes network latency between the | ||
| service and Postgres. | ||
| - In a separate-host topology, the service runs on a dedicated host | ||
| with no database instance, which isolates the service workload from | ||
| the database. | ||
| - In a multiple-instances topology, one service instance runs per host | ||
| for redundancy or regional proximity; each instance receives its own | ||
| credentials and connects to the database independently. | ||
|
|
||
| In the following example, the service runs on the same host as the | ||
| database node (`host-1`): | ||
|
|
||
| ```json | ||
| "nodes": [ { "name": "n1", "host_ids": ["host-1"] } ], | ||
| "services": [ { ..., "host_ids": ["host-1"] } ] | ||
| ``` | ||
|
|
||
| In the following example, the service runs on a dedicated host | ||
| (`host-3`) with no database instance: | ||
|
|
||
| ```json | ||
| "nodes": [ { "name": "n1", "host_ids": ["host-1"] }, | ||
| { "name": "n2", "host_ids": ["host-2"] } ], | ||
| "services": [ { ..., "host_ids": ["host-3"] } ] | ||
| ``` | ||
|
|
||
| In the following example, the service runs on each database host, | ||
| creating one instance per host for redundancy: | ||
|
|
||
| ```json | ||
| "nodes": [ { "name": "n1", "host_ids": ["host-1"] }, | ||
| { "name": "n2", "host_ids": ["host-2"] } ], | ||
| "services": [ { ..., "host_ids": ["host-1", "host-2"] } ] | ||
| ``` | ||
|
|
||
| ## Database Credentials | ||
|
|
||
| Each service instance is automatically provisioned with two dedicated | ||
| database users. The Control Plane manages these credentials; you do not | ||
| need to create or rotate them manually. The credentials are: | ||
|
|
||
| - `svc_{service_id}_ro` is a read-only user with read access to the | ||
| database; this user is the default for most service types. | ||
| - `svc_{service_id}_rw` is a read-write user with read and write access | ||
| to the database; this user is provisioned when the service needs | ||
| read/write access. | ||
|
|
||
| ## Next Steps | ||
|
|
||
| To add a service to a database, see [Managing Services](managing.md). | ||
| Then refer to the page for your specific service type for configuration | ||
| details. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| # Managing Services | ||
|
|
||
| Services are declared as part of your database spec. You add, update, | ||
| and remove services by modifying the `services` array in a | ||
| `create_database` or `update_database` request. See the | ||
| [Services Overview](index.md) for a conceptual introduction. | ||
|
|
||
| ## Service Spec Fields | ||
|
|
||
| Each service in the `services` array is declared using a service spec. | ||
| The following table describes the fields in a service spec: | ||
|
|
||
| | Field | Type | Required | Description | | ||
| |-------|------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| | `service_id` | string | Yes | A unique identifier for this service within the database. Used in credential names (`svc_{service_id}_ro` / `svc_{service_id}_rw`). | | ||
| | `service_type` | string | Yes | The type of service to run. One of: `mcp`, `rag`, `postgrest`. | | ||
| | `version` | string | Yes | The service version in semver format (e.g., `1.0.0`) or the literal `latest`. | | ||
| | `host_ids` | array | Yes | The IDs of the hosts to run this service on. One instance is created per host. | | ||
| | `config` | object | Yes | Service-type-specific configuration. See the page for your service type for valid fields. | | ||
| | `port` | integer | No | Host port to publish the service on. Set to `0` to let Docker assign a random port. When omitted, the service is not reachable from outside the Docker network. | | ||
| | `cpus` | string | No | CPU limit for the service container. Accepts a decimal (e.g., `"0.5"`) or millicpu suffix (e.g., `"500m"`). Defaults to container defaults if unspecified. | | ||
| | `memory` | string | No | Memory limit for the service container in SI or IEC notation (e.g., `"512M"`, `"1GiB"`). Defaults to container defaults if unspecified. | | ||
| | `database_connection` | object | No | Optional routing configuration for how the service connects to the database. See [Database Connection Routing](#database-connection-routing). | | ||
|
|
||
| ## Adding a Service | ||
|
|
||
| Include a `services` array in your database spec when creating or | ||
| updating a database. In the following example, a `curl` command creates | ||
| a single-node database with one MCP service instance: | ||
|
|
||
| === "curl" | ||
|
|
||
| ```sh | ||
| curl -X POST http://host-1:3000/v1/databases \ | ||
| -H 'Content-Type: application/json' \ | ||
| --data '{ | ||
| "id": "example", | ||
| "spec": { | ||
| "database_name": "example", | ||
| "nodes": [ | ||
| { "name": "n1", "host_ids": ["host-1"] } | ||
| ], | ||
| "services": [ | ||
| { | ||
| "service_id": "mcp-server", | ||
| "service_type": "mcp", | ||
| "version": "latest", | ||
| "host_ids": ["host-1"], | ||
| "port": 8080, | ||
| "config": { | ||
| "llm_enabled": true, | ||
| "llm_provider": "anthropic", | ||
| "llm_model": "claude-sonnet-4-5", | ||
| "anthropic_api_key": "sk-ant-..." | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| }' | ||
| ``` | ||
|
|
||
| The response includes a task ID you can use to track progress. See | ||
| [Tasks & Logs](../using/tasks-logs.md) for details. | ||
|
|
||
| ## Updating a Service | ||
|
|
||
| To update a service's configuration, submit a `POST` request to | ||
| `/v1/databases/{database_id}` with the modified service spec in the | ||
| `services` array. | ||
|
|
||
| !!! important | ||
|
|
||
| The `services` array in an update request is declarative; it | ||
| replaces the complete list of services for the database. To keep an | ||
| existing service running unchanged, include its current spec | ||
| alongside any new or modified entries. | ||
|
|
||
| In the following example, a `curl` command updates the MCP service to | ||
| use a different model: | ||
|
|
||
| === "curl" | ||
|
|
||
| ```sh | ||
| curl -X POST http://host-1:3000/v1/databases/example \ | ||
| -H 'Content-Type: application/json' \ | ||
| --data '{ | ||
| "spec": { | ||
| "database_name": "example", | ||
| "nodes": [ | ||
| { "name": "n1", "host_ids": ["host-1"] } | ||
| ], | ||
| "services": [ | ||
| { | ||
| "service_id": "mcp-server", | ||
| "service_type": "mcp", | ||
| "version": "latest", | ||
| "host_ids": ["host-1"], | ||
| "port": 8080, | ||
| "config": { | ||
| "llm_enabled": true, | ||
| "llm_provider": "anthropic", | ||
| "llm_model": "claude-opus-4-5", | ||
| "anthropic_api_key": "sk-ant-..." | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| }' | ||
| ``` | ||
|
|
||
| ## Removing a Service | ||
|
|
||
| To remove a service, submit an update request that omits the service | ||
| from the `services` array. The Control Plane stops and deletes all | ||
| service instances for that service and revokes its database credentials. | ||
|
|
||
| !!! warning | ||
|
|
||
| Removing a service is irreversible. The Control Plane deletes all | ||
| service instances, their configuration, and their data directories. | ||
| Database credentials for the service are revoked. Any clients | ||
| connected to the service lose access immediately. | ||
|
|
||
| ## Checking Service Status | ||
|
|
||
| To check the current state of your service instances, retrieve the | ||
| database and inspect the `service_instances` field in the response. In | ||
| the following example, a `curl` command retrieves the database: | ||
|
|
||
| === "curl" | ||
|
|
||
| ```sh | ||
| curl http://host-1:3000/v1/databases/example | ||
| ``` | ||
|
|
||
| Each service instance in the response includes a `state` field. See the | ||
| [Services Overview](index.md#service-instances) for a description of | ||
| each state. | ||
|
|
||
| ## Database Connection Routing | ||
|
|
||
| By default, the Control Plane builds a connection string that includes | ||
| all database nodes, with the local node listed first. You can override | ||
| this behavior using the `database_connection` field in the service spec. | ||
| The following table describes the `database_connection` fields: | ||
|
|
||
| | Field | Type | Description | | ||
| |-------|------|-------------| | ||
| | `target_nodes` | array of strings | An ordered list of node names to include in the connection string. Nodes are tried in the order listed. | | ||
| | `target_session_attrs` | string | Overrides the libpq `target_session_attrs` parameter. Valid values: `primary`, `prefer-standby`, `standby`, `read-write`, `any`. | | ||
|
|
||
| In the following example, the `database_connection` field routes the | ||
| service to the `n1` node only: | ||
|
|
||
| === "curl" | ||
|
|
||
| ```sh | ||
| "database_connection": { | ||
| "target_nodes": ["n1"], | ||
| "target_session_attrs": "primary" | ||
| } | ||
| ``` | ||
|
|
||
| !!! tip | ||
|
|
||
| Use `database_connection` when your service needs to read from a | ||
| specific node or enforce write routing to the primary. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.