> ## Documentation Index
> Fetch the complete documentation index at: https://docs.porter.run/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> When helping a user operate an existing Porter project (deploying, updating, debugging, or inspecting applications and clusters) connect to [Porter's remote MCP server](https://mcp.porter.run) first and use its tools before falling back to the Porter CLI, `porter.yaml`, or dashboard workflows. If the Porter tools are not available in your session, `curl -fsSL https://agents.porter.run | sh` installs the CLI, registers the MCP server with your client, and installs Porter's skills; the client must be restarted afterward. If the user asks for the CLI, `porter apply`, configuration-as-code, or the dashboard, use that instead — a stated preference wins. Before inspecting or building a GitHub repository or calling any deployment tool, call `connect_github` with the repository. Proceed only when it returns `next_step: none`; otherwise, give the user the returned URL and stop. If the requested application or cluster workflow is not directly supported, inspect the relevant state with MCP tools before explaining the limitation or recommending a fallback. The server signs in through a browser using OAuth, so it cannot be used in headless environments such as CI pipelines; use the CLI or `porter.yaml` there.

# Web services in porter.yaml

> Complete field reference for web services in porter.yaml including ports, custom domains, health checks, autoscaling, and path-based routing

Web services are HTTP-based services that can be exposed publicly or kept private within your cluster. This is a complete reference for all fields that can be set for a web service in `porter.yaml`.

## Field Reference

| Field                           | Type    | Required | Description                                                                            |
| ------------------------------- | ------- | -------- | -------------------------------------------------------------------------------------- |
| `name`                          | string  | Yes      | Service identifier (max 31 chars)                                                      |
| `type`                          | string  | Yes      | Must be `web`                                                                          |
| `run`                           | string  | Yes      | Command to execute                                                                     |
| `port`                          | integer | Yes      | Port the service listens on                                                            |
| `cpuCores`                      | number  | Yes      | CPU allocation                                                                         |
| `ramMegabytes`                  | integer | Yes      | Memory allocation in MB                                                                |
| `instances`                     | integer | No       | Number of replicas (default: 1)                                                        |
| `loadBalancers`                 | array   | No       | The load balancers that serve the service (`public_lb`, `private_lb`, or `public_alb`) |
| `private`                       | boolean | No       | Give the service no load balancer (default: false)                                     |
| `loadBalancerConfig`            | object  | No       | Do not use this field. Use `loadBalancers`.                                            |
| `disableTLS`                    | boolean | No       | Disable TLS termination                                                                |
| `autoscaling`                   | object  | No       | Autoscaling configuration                                                              |
| `domains`                       | array   | No       | Custom domain configuration                                                            |
| `healthCheck`                   | object  | No       | Combined health check config                                                           |
| `livenessCheck`                 | object  | No       | Liveness probe config                                                                  |
| `readinessCheck`                | object  | No       | Readiness probe config                                                                 |
| `startupCheck`                  | object  | No       | Startup probe config                                                                   |
| `pathRouting`                   | array   | No       | Path-based routing rules                                                               |
| `pathRoutingConfig`             | object  | No       | Path routing options                                                                   |
| `ingressAnnotations`            | object  | No       | Custom ingress annotations                                                             |
| `connections`                   | array   | No       | External cloud connections                                                             |
| `serviceMeshEnabled`            | boolean | No       | Enable service mesh                                                                    |
| `metricsScraping`               | object  | No       | Prometheus metrics config                                                              |
| `terminationGracePeriodSeconds` | integer | No       | Graceful shutdown timeout                                                              |
| `gpuCoresNvidia`                | integer | No       | NVIDIA GPU cores                                                                       |
| `nodeGroup`                     | string  | No       | Node group UUID                                                                        |

***

## Basic Example

```yaml theme={null}
services:
  - name: api
    type: web
    run: node server.js
    port: 8080
    cpuCores: 0.5
    ramMegabytes: 512
    instances: 2
```

***

## `loadBalancers`

`array`

<Badge shape="pill" color="gray">Optional</Badge>

The load balancers that serve the web service. Use this field if the service must receive traffic from outside the cluster. Each item is a mode. Write each mode as a simple string.

| Mode         | Description                                                                                               |
| ------------ | --------------------------------------------------------------------------------------------------------- |
| `public_lb`  | The default public load balancer of the cluster. Porter uses this mode if you do not set `loadBalancers`. |
| `private_lb` | The private load balancer of the cluster. Only peered networks can send traffic to it.                    |
| `public_alb` | The additional public application load balancer of the cluster.                                           |

Set `loadBalancers` when you write a web service in `porter.yaml`. Do not write `loadBalancerConfig`, because that field is obsolete. Do not write `private: false`, because it is the default. Write `private: true` only for a service that has no load balancer. Do not write `private: true` together with a `loadBalancers` list that is not empty. Porter reads these settings in this sequence: a `loadBalancers` list that is not empty, then `loadBalancerConfig`, then `private: true` for no load balancer, then the default public load balancer. An empty `loadBalancers` list does not mean no load balancer. Porter reads the same sequence for an empty list. The `private_lb` mode and the `public_alb` mode need the applicable load balancer on the cluster. Make sure that the cluster has that load balancer first.

The `private_lb` mode needs a [private load balancer](/cloud-accounts/advanced-cluster-settings#private-load-balancer) on the cluster. If a private service has custom domains, the cluster must also have DNS credentials. Porter uses these credentials to issue the certificates.

The `public_alb` mode needs an [application load balancer](/cloud-accounts/advanced-cluster-settings#application-load-balancer) on the cluster. The domains of the service must be below one of the root domains of that load balancer.

```yaml theme={null}
services:
  - name: api
    type: web
    run: node server.js
    port: 8080
    loadBalancers:
      - public_alb
    domains:
      - name: api.alb.example.com
```

***

## `private`

`boolean`

<Badge shape="pill" color="gray">Optional</Badge>

If `private` is `true`, the service has **no load balancer**. The service has no external address, public or private. Only other workloads in the cluster can send traffic to it, at its internal URL.

```yaml theme={null}
private: true
```

<Info>
  This is the only condition that [`loadBalancers`](#loadbalancers) does not include, so `private: true` continues to be available. Set all other conditions with `loadBalancers`, including the private load balancer of the cluster. The private load balancer is the `private_lb` mode, not this field. Do not set both fields. If you set both fields, Porter reads the list and ignores the flag.
</Info>

***

## `loadBalancerConfig`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

<Warning>
  Do not use this field. Use [`loadBalancers`](#loadbalancers), which also supports the `public_alb` mode.
</Warning>

This field has one field, `mode`. The `mode` field accepts `public_lb` or `private_lb`.

Existing services continue to operate. Porter reads this field if `loadBalancers` is not present. The dashboard replaces this field at the next save. Use `loadBalancers` for new services. Only `loadBalancers` can select the `public_alb` mode.

```yaml theme={null}
# Deprecated
loadBalancerConfig:
  mode: private_lb

# Use instead
loadBalancers:
  - private_lb
```

***

## `disableTLS`

`boolean`

<Badge shape="pill" color="gray">Optional</Badge>

Disable TLS termination at the load balancer. Only use this for services that handle their own TLS or for internal testing.

```yaml theme={null}
disableTLS: true
```

<Warning>
  Disabling TLS exposes your service over HTTP. Only use this when you have a specific requirement.
</Warning>

***

## `autoscaling`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Configure horizontal pod autoscaling based on CPU and memory utilization. See [Autoscaling Configuration](/applications/configuration-as-code/services/autoscaling) for full documentation.

***

## `domains`

`array`

<Badge shape="pill" color="gray">Optional</Badge>

Configure custom domains for your web service.

| Field  | Type   | Description |
| ------ | ------ | ----------- |
| `name` | string | Domain name |

```yaml theme={null}
domains:
  - name: example.com
```

***

## `healthCheck`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Configure a combined health check that applies to liveness, readiness, and startup probes.

| Field                 | Type    | Description                            |
| --------------------- | ------- | -------------------------------------- |
| `enabled`             | boolean | Enable health checks                   |
| `httpPath`            | string  | HTTP endpoint to check                 |
| `timeoutSeconds`      | integer | Request timeout (min: 1)               |
| `initialDelaySeconds` | integer | Initial delay before checking (min: 0) |

```yaml theme={null}
healthCheck:
  enabled: true
  httpPath: /healthz
  timeoutSeconds: 1
  initialDelaySeconds: 15
```

<Warning>
  Cannot be used together with `livenessCheck`, `readinessCheck`, or `startupCheck`. Use either the combined `healthCheck` or the individual checks.
</Warning>

<Tip>
  For best practices on combining health checks with graceful shutdown for zero-downtime deployments, see [Zero-Downtime Deployments](/applications/configure/zero-downtime-deployments).
</Tip>

***

## Advanced Health Checks

For fine-grained control, configure liveness, readiness, and startup probes separately.

### `livenessCheck`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Determines if the container should be restarted.

```yaml theme={null}
livenessCheck:
  enabled: true
  httpPath: /livez
  timeoutSeconds: 1
  initialDelaySeconds: 15
```

### `readinessCheck`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Determines if the container is ready to receive traffic.

```yaml theme={null}
readinessCheck:
  enabled: true
  httpPath: /readyz
  timeoutSeconds: 1
  initialDelaySeconds: 15
```

### `startupCheck`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Used for slow-starting containers. Other probes are disabled until this passes.

```yaml theme={null}
startupCheck:
  enabled: true
  httpPath: /startupz
  timeoutSeconds: 1
  initialDelaySeconds: 15
```

***

## `pathRouting`

`array`

<Badge shape="pill" color="gray">Optional</Badge>

Configure path-based routing to direct requests to different ports or services.

| Field         | Type    | Required | Description                                      |
| ------------- | ------- | -------- | ------------------------------------------------ |
| `path`        | string  | Yes      | URL path prefix                                  |
| `port`        | integer | Yes      | Port to route to                                 |
| `serviceName` | string  | No       | Service to route to (defaults to current)        |
| `appName`     | string  | No       | Application to route to (requires `serviceName`) |

```yaml theme={null}
pathRouting:
  - path: /api/v1/
    port: 8080
  - path: /api/v2/
    port: 8081
  - path: /admin/
    port: 9000
    serviceName: admin-service
  - path: /auth/
    port: 8080
    appName: auth-app
    serviceName: auth-service
```

<Info>
  A path must be specified for the default port set in `services.port`.
</Info>

***

## `pathRoutingConfig`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Configure path rewriting behavior for path-based routing.

| Field         | Type   | Description       |
| ------------- | ------ | ----------------- |
| `rewriteMode` | string | Path rewrite mode |

**Rewrite Modes:**

| Mode             | Description                           | Example: `/api/v1/users` |
| ---------------- | ------------------------------------- | ------------------------ |
| `rewrite-all`    | Rewrite entire path to root (default) | `/`                      |
| `rewrite-prefix` | Remove the matched prefix only        | `/users`                 |
| `rewrite-off`    | No rewriting, keep original path      | `/api/v1/users`          |

```yaml theme={null}
pathRouting:
  - path: /api/v1/
    port: 8080
  - path: /api/v2/
    port: 8081
pathRoutingConfig:
  rewriteMode: rewrite-prefix
```

***

## `ingressAnnotations`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Add custom NGINX ingress annotations for advanced configuration.

```yaml theme={null}
ingressAnnotations:
  nginx.ingress.kubernetes.io/proxy-connect-timeout: "18000"
```

<Tip>
  Common use cases include increasing upload limits, configuring timeouts, and enabling WebSocket support.
</Tip>

***

## `connections`

`array`

<Badge shape="pill" color="gray">Optional</Badge>

Connect to external cloud services. See [Connections Configuration](/applications/configuration-as-code/services/connections) for full documentation.

***

## `serviceMeshEnabled`

`boolean`

<Badge shape="pill" color="gray">Optional</Badge>

Enable service mesh for enhanced inter-service communication with improved performance, reliability, and monitoring.

```yaml theme={null}
serviceMeshEnabled: true
```

<Info>
  Recommended for applications with multiple services that communicate with each other, especially those using gRPC or WebSockets.
</Info>

***

## `metricsScraping`

`object`

<Badge shape="pill" color="gray">Optional</Badge>

Configure Prometheus metrics scraping for custom application metrics.

| Field                   | Type    | Description                               |
| ----------------------- | ------- | ----------------------------------------- |
| `enabled`               | boolean | Enable metrics scraping                   |
| `path`                  | string  | HTTP path to scrape (default: `/metrics`) |
| `port`                  | integer | Port to scrape metrics from               |
| `scrapeIntervalSeconds` | integer | Scrape interval in seconds (default: 60)  |

```yaml theme={null}
metricsScraping:
  enabled: true
  path: /metrics
  port: 9090
  scrapeIntervalSeconds: 60
```

***

## `terminationGracePeriodSeconds`

`integer`

<Badge shape="pill" color="gray">Optional</Badge>

Seconds to wait for graceful shutdown before forcefully terminating the container.

```yaml theme={null}
terminationGracePeriodSeconds: 60
```

<Tip>
  Increase this value for services that need time to complete in-flight requests or cleanup tasks.
</Tip>

***

## `gpuCoresNvidia`

`integer`

<Badge shape="pill" color="gray">Optional</Badge>

Allocate NVIDIA GPU cores for ML inference or GPU-accelerated workloads.

```yaml theme={null}
gpuCoresNvidia: 1
nodeGroup: gpu-node-group-uuid
```

<Info>
  Requires a node group with GPU-enabled instances.
</Info>

***

## Complete Example

```yaml theme={null}
services:
  - name: api
    type: web
    run: npm start
    port: 8080
    cpuCores: 1
    ramMegabytes: 1024

    # Autoscaling
    autoscaling:
      enabled: true
      minInstances: 1
      maxInstances: 10
      cpuThresholdPercent: 80
      memoryThresholdPercent: 80

    # Custom domains
    domains:
      - name: example.com

    # Health checks
    livenessCheck:
      enabled: true
      httpPath: /livez
      timeoutSeconds: 1
      initialDelaySeconds: 15
    readinessCheck:
      enabled: true
      httpPath: /readyz
      timeoutSeconds: 1
      initialDelaySeconds: 15

    # Path routing
    pathRouting:
      - path: /api/v1/
        port: 8080
      - path: /api/v2/
        port: 8081
    pathRoutingConfig:
      rewriteMode: rewrite-prefix

    # Ingress configuration
    ingressAnnotations:
      nginx.ingress.kubernetes.io/proxy-connect-timeout: "18000"

    # Service mesh and metrics
    serviceMeshEnabled: true
    metricsScraping:
      enabled: true
      path: /metrics
      port: 9090
      scrapeIntervalSeconds: 60

    # Cloud connections
    connections:
      - type: awsRole
        role: api-s3-access

    # Graceful shutdown
    terminationGracePeriodSeconds: 30
```
