# How Auto Port Selection Works for Frontend and Backend Services in Lifetrace

> Discover how Lifetrace's auto port selection effortlessly finds available ports for your FastAPI backend and Next.js frontend, eliminating manual configuration even when defaults are busy.

- Repository: [FreeU-group/lifetrace](https://github.com/freeu-group/lifetrace)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Lifetrace automatically detects occupied ports and increments sequentially until finding an available one, allowing both the FastAPI backend and Next.js frontend to start without manual configuration even when default ports are busy.**

Lifetrace implements a dynamic port allocation system to eliminate conflicts when running multiple instances simultaneously. The repository uses custom port discovery mechanisms for both the FastAPI backend service and the Next.js frontend development server, ensuring developers can run production builds alongside development versions without encountering port collision errors.

## Backend Auto Port Selection (FastAPI)

### Configuration and Default Port

The backend service defines its default port in the Dynaconf settings. The configuration specifies `8001` as the primary port via `settings.server.port`. This value serves as the starting point for the port discovery process in [`lifetrace/server.py`](https://github.com/freeu-group/lifetrace/blob/main/lifetrace/server.py).

### The Port Finder Mechanism

Before launching the Uvicorn server, the script invokes `find_available_port(host, start_port)`. The implementation creates a temporary `socket.socket(AF_INET, SOCK_STREAM)` and attempts to bind to the host and starting port. If the bind operation fails due to the port being occupied, the function increments the port number and retries. This process continues for up to `max_attempts` (defaulting to 100) until a successful bind identifies an available port.

### Logging Port Switches

When the selected port differs from the originally configured default, the backend logs an informational message noting the automatic port switch. This provides visibility to developers that the service is running on a non-standard port due to availability constraints.

## Frontend Auto Port Selection (Next.js)

### Default Port and Detection Logic

The frontend development script located at [`free-todo-frontend/scripts/dev-with-auto-port.js`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/scripts/dev-with-auto-port.js) hard-codes `3001` as the default starting port. The helper function `findAvailablePort(startPort, maxAttempts)` utilizes Node.js's `net.createServer()` to test port availability. It attempts to listen on the specified port using IPv6 notation (`"::"`), which also binds to IPv4. If the listen operation succeeds, the port is confirmed as available; otherwise, the function proceeds to the next sequential port. The search continues for up to `MAX_PORT_ATTEMPTS` (100 iterations).

### Backend Discovery Mechanism

Before launching the Next.js development server, the frontend script executes `findRunningBackendPort()` to locate the active Lifetrace backend. This function first queries the priority ports `[8001, 8000]`—representing the development and build defaults—via the `/health` endpoint. If neither responds, the script performs a sequential scan of ports `8002` through `8099`. Upon detecting a responsive backend, the script exports the discovered URL as `NEXT_PUBLIC_API_URL`, ensuring the frontend communicates with the correct backend instance regardless of which port it occupies.

### CORS Configuration for Dynamic Ports

To accommodate the dynamic port allocation, the backend implements a `get_cors_origins` function in [`lifetrace/server.py`](https://github.com/freeu-group/lifetrace/blob/main/lifetrace/server.py) that generates allowed origin patterns covering the entire possible port range. The configuration explicitly allows origins from ports `3000-3200` for frontend services and `8000-8200` for backend services. This ensures that regardless of which specific ports the auto-selection mechanism chooses, the browser permits cross-origin requests without CORS errors.

## Practical Usage Examples

Start the backend service with automatic port fallback:

```bash

# Uses default 8001, or finds next available (8002, 8003, etc.)

python -m lifetrace.server

# Override starting port while keeping auto-fallback

python -m lifetrace.server --port 8010

```

Start the frontend development server with automatic port and backend detection:

```bash

# From the frontend directory

pnpm dev

# Expected output shows dynamic configuration:

#   Frontend port: 3002

#   Detected FreeTodo backend running on port: 8001

#   Backend API: http://localhost:8001

```

## Summary

- **Backend auto port selection** uses a socket binding mechanism in [`lifetrace/server.py`](https://github.com/freeu-group/lifetrace/blob/main/lifetrace/server.py) to test availability starting from port `8001`, incrementing until finding an open port up to 100 attempts.
- **Frontend auto port selection** implemented in [`free-todo-frontend/scripts/dev-with-auto-port.js`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/scripts/dev-with-auto-port.js) tests ports starting from `3001` using Node.js server creation, with similar fallback logic.
- **Backend discovery** allows the frontend to automatically locate the running FastAPI service by checking priority ports `[8001, 8000]` followed by a scan of `8002-8099` via the `/health` endpoint.
- **CORS pre-configuration** covers port ranges `3000-3200` and `8000-8200` to ensure seamless communication regardless of which specific ports are dynamically selected.

## Frequently Asked Questions

### What happens if all 100 port attempts are exhausted?

If the port finder functions exhaust their maximum attempt limits (100 iterations), the backend raises a runtime exception indicating no available ports were found, while the frontend script logs a fatal error and exits the development server startup process. This prevents silent failures and alerts the developer to resolve port conflicts manually.

### Can I disable auto port selection and force a specific port?

Yes, you can override the starting port for the backend using the `--port` command-line argument, though the system will still fall back to the next available port if your specified port is occupied. For the frontend, you can modify the `DEFAULT_PORT` constant in [`free-todo-frontend/scripts/dev-with-auto-port.js`](https://github.com/freeu-group/lifetrace/blob/main/free-todo-frontend/scripts/dev-with-auto-port.js) or set environment variables if the script supports them, though the repository primarily relies on the automatic detection mechanism.

### How does the frontend know which backend port to use?

The frontend development script runs `findRunningBackendPort()` before starting the Next.js server, which probes the `/health` endpoint on priority ports `[8001, 8000]` and then scans the range `8002-8099` to locate the active FastAPI instance. Once found, it exports the discovered URL as `NEXT_PUBLIC_API_URL`, ensuring the frontend build targets the correct backend regardless of which port was dynamically selected.

### Does the CORS configuration support all possible auto-selected ports?

The CORS configuration in [`lifetrace/server.py`](https://github.com/freeu-group/lifetrace/blob/main/lifetrace/server.py) pre-defines allowed origin ranges covering ports `3000-3200` for frontend services and `8000-8200` for backend services through the `get_cors_origins` function. This ensures that any port automatically selected within these ranges will be permitted for cross-origin requests without requiring manual CORS configuration updates.