How Auto Port Selection Works for Frontend and Backend Services in Lifetrace
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.
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 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 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:
# 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:
# 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.pyto test availability starting from port8001, incrementing until finding an open port up to 100 attempts. - Frontend auto port selection implemented in
free-todo-frontend/scripts/dev-with-auto-port.jstests ports starting from3001using 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 of8002-8099via the/healthendpoint. - CORS pre-configuration covers port ranges
3000-3200and8000-8200to 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →