Nginx · The edge of your stack

How do you design a useful access log format?

Mediumlog_formatobservabilityjson logsUpdated Oct 2026
Quiz this track

Short answer

Log request time, status, upstream address and timing, cache status and a request ID. Use escape=json for machine parsing and keep untrusted values properly escaped.

The default combined format is readable but weak for debugging latency and upstream failures. A production format should let you separate time spent in Nginx from time spent in the backend and correlate a request across services.

nginx
log_format json escape=json '{'
    '"time":"$time_iso8601",'
    '"request_id":"$request_id",'
    '"remote_addr":"$remote_addr",'
    '"method":"$request_method",'
    '"uri":"$request_uri",'
    '"status":$status,'
    '"request_time":$request_time,'
    '"upstream_time":"$upstream_response_time",'
    '"upstream_addr":"$upstream_addr",'
    '"cache":"$upstream_cache_status"'
'}';

access_log /var/log/nginx/access.log json;

Fields worth including

  • $request_time measures the whole request as seen by Nginx
  • $upstream_response_time isolates backend time and can contain several values after retries
  • $upstream_addr shows which backend served the request
  • $request_id lets you correlate Nginx with application logs
  • $upstream_cache_status distinguishes HIT, MISS, BYPASS and EXPIRED
JSON escaping prevents a crafted header or URI from breaking the log structure. Be careful with $http_x_forwarded_for, because the client controls it unless a trusted proxy overwrites it.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What is the difference between $request_time and $upstream_response_time?
  2. 2Why is escape=json important?
  3. 3How does $request_id help debugging?
  4. 4What does an upstream_time with multiple values mean?

Say it in the interview

I design the access log around debugging and aggregation: status, request time, upstream time and address, cache status and a request ID. I use JSON escaping so the log is machine-parseable and cannot be broken by crafted input. request_time includes client network time, while upstream_response_time isolates the backend. Multiple upstream times indicate retries or internal redirects.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Nginx mock interview and get scored feedback on depth, clarity and confidence.