Access logs
Access logs list every request your app serves: when it arrived, the visitor's address, the page, the status code, how long it took and how much was sent back. They're recorded where requests come in, before they reach your app, so you don't add anything to your code. They're on every plan at no extra cost.
Access logs are about traffic. What your app prints, its errors and start-up messages, is on the Logs tab.
View them in the dashboard
Open the app and go to the Access logs tab. The newest requests are at the top. With Live on, new ones are added every five seconds; a request usually appears within a few seconds of being served.
Filter by:
- Status: 2xx, 3xx, 4xx, 5xx, or 4xx and 5xx together.
- Method: GET, POST and so on.
- Path: any part of it, not case-sensitive.
- Visitor IP.
Click a row to see everything recorded for it: the full URL, protocol, user agent, referrer, bytes received and sent, the request ID, and two timings:
- Time at your app is how long your app took to send back its response headers.
- Total time is the whole request, including sending the response to the visitor.
When total time is much higher than time at your app, the delay is in getting a large response to the visitor, not in your code.
Load older pages back through older requests.
What's recorded
Every request that reaches your app through velixir, on every hostname it has: its velixir.run address, custom domains and deployment slots. Each line includes the hostname, so you can tell them apart.
That includes requests that never reached your app because the platform turned them away: a request the WAF blocked (403) or one over your rate limit (429). If you've switched on a security setting, this is where you can see it working.
A WebSocket appears once, when the connection closes, with everything sent over it in that time.
For each request we record the time, method, URL including the query string, protocol, status, bytes in and out, both timings, the visitor's IP address, user agent, referrer, hostname and a request ID. We don't record request bodies, cookies or other headers. Anything in a URL is recorded, so keep secrets such as tokens out of query strings.
From the CLI
Inside a linked project, or with --app <id>:
velixir access-logs # the last 50 requests, newest at the bottom
velixir access-logs -f # keep printing new requests as they arrive
velixir access-logs --status 5xx --since 1h # server errors in the last hour
velixir access-logs --path /api --method POST
velixir access-logs --json | jq .requestTimeMs
| Option | What it does |
|---|---|
--follow, -f |
Keep printing new requests until you press Ctrl+C. |
--since, -S <dur> |
Only requests from the last 30s, 15m, 2h, 1d and so on. |
--status, -s <filter> |
2xx, 3xx, 4xx, 5xx, errors (4xx and 5xx), or a code such as 404. |
--method, -m <method> |
Only this HTTP method. |
--path, -p <text> |
Only paths containing this text, not case-sensitive. |
--ip, -i <address> |
Only requests from this visitor IP. |
--host, -H <host> |
Only requests to this hostname. |
--limit, -n <n> |
How many to show, 1 to 500 (default 50). |
--json |
One JSON object per line, in the API's format. |
velixir requests is the same command.
From the API
curl -H "X-Api-Key: $VELIXIR_API_KEY" \
"https://velixir.net/api/v1/apps/<app-id>/access-logs?status=5xx&limit=100"
Query parameters, all optional:
| Parameter | Meaning |
|---|---|
status |
2xx, 3xx, 4xx, 5xx, errors, or a code such as 404. |
method |
HTTP method. |
path |
Text the path contains, not case-sensitive. |
ip |
Visitor IP address. |
host |
Exact hostname. |
before |
ISO 8601 time: only requests older than this. |
after |
ISO 8601 time: only requests newer than this. |
limit |
1 to 500, default 100. |
Requests come back newest first:
{
"appId": "…",
"count": 100,
"nextBefore": "2026-10-09T14:02:07.412Z",
"entries": [
{
"timestamp": "2026-10-09T14:02:09.120Z",
"host": "shop-de.velixir.run",
"method": "POST",
"path": "/api/pay",
"query": "",
"protocol": "HTTP/2.0",
"status": 503,
"bytesSent": 207,
"requestLength": 412,
"requestTimeMs": 31,
"upstreamTimeMs": 30,
"clientIp": "203.0.113.24",
"userAgent": "Mozilla/5.0 …",
"referer": "https://shop.example.com/cart",
"requestId": "9737172cff321039b94fbfbd7da3fc23"
}
]
}
To page back, pass nextBefore as before on the next call; it's null once there's nothing more. To follow new requests, poll with after set a little before the newest timestamp you have and skip requestIds you've already seen, because requests can arrive a few seconds out of order. That's what the CLI's -f does.
The key needs read access to the app (see API keys). The endpoint returns 503 if access logs are briefly unavailable.
For AI agents
The MCP server (npx -y @velixir/mcp) has an access_logs tool with the same filters. An agent can read the access logs of an app it deployed itself, by the deployment ID the deploy tool returned, until a person claims the app. For apps you own, set VELIXIR_API_KEY in the MCP server's environment and pass the app's ID.
How long they're kept
- Free plan: 24 hours.
- Paid plans: 7 days.
After that, requests are deleted automatically. If you change plan, new requests are kept for the new plan's period. Each request includes the visitor's IP address, which is personal data, so we keep access logs only as long as they're useful for debugging. If you need a longer history, export them with the API or velixir access-logs --json and store them yourself.
What access logs aren't for
- Your app's own output. Errors, stack traces and anything your app prints are on the Logs tab.
- Analytics. Access logs are every raw request, including bots and uptime monitors. Use an analytics tool for visitor counts and trends.
- A permanent record. They're kept for a day or a week (see above).