Skip to main content

Using Subdomains

Subdomains let you organize multiple related services under a common parent domain:
Each service gets its own URL, but they share a common namespace (myapp.localhost).

Wildcard Subdomain Routing

Portless automatically routes wildcard subdomains to the longest matching registered route.

How It Works

Routing Priority

Portless matches routes with the following priority:
  1. Exact match: api.myapp.localhost matches api.myapp.localhost (if registered)
  2. Wildcard match: tenant1.api.myapp.localhost matches api.myapp.localhost
  3. Longer suffix match: If both myapp.localhost and api.myapp.localhost are registered, tenant1.api.myapp.localhost routes to api.myapp.localhost (longer suffix wins)

Multi-Tenant Applications

Wildcard routing is ideal for multi-tenant apps where each tenant gets their own subdomain:
Your app can extract the tenant ID from the Host header:

Monorepo Service Organization

In a monorepo, use subdomains to namespace services:
Now you have:
  • Frontend: http://frontend.myapp.localhost:1355
  • API: http://api.myapp.localhost:1355
  • Docs: http://docs.myapp.localhost:1355
You can also use portless run to infer the service name from package.json. If you set "name": "frontend", then portless run next dev will automatically use frontend.localhost as the hostname.

Cross-Service Communication

When one service needs to call another, use the portless URL:
When proxying between portless apps, always set changeOrigin: true. Without it, the proxy forwards the original Host header, causing portless to route the request back to the frontend in an infinite loop.Portless detects this and responds with 508 Loop Detected along with a helpful error message.

Environment-Specific URLs

Use the PORTLESS_URL environment variable to reference the current service’s URL:

Combining Subdomains with Worktrees

Subdomains and worktree prefixes compose naturally:
The worktree prefix (auth) is prepended to the full service name.

DNS Label Length Limit

DNS labels (the parts between dots) are limited to 63 characters per RFC 1035. Portless automatically truncates long labels and appends a hash suffix for uniqueness:
Example:

Static Aliases for Non-Portless Services

Use portless alias to register routes for services not managed by portless (e.g., Docker containers, databases):
Aliases show up in portless list with (alias) instead of a PID:

Subdomain Naming Best Practices

Use Short, Descriptive Names

Use Consistent Naming

Wildcard Routing Edge Cases

Deep Nesting

Wildcard routing works at any depth:

Overlapping Routes

If you register multiple overlapping routes, the longest suffix wins: