On this page
Why Should Servers Always Use UTC?
Servers should store and log time in UTC so logs, timestamps, and schedules agree across machines and time zones. Learn why and how to switch.
Quick answer
- UTC is the single reference clock every machine can agree on; local time zones differ per machine and shift twice a year.
- Logs and database timestamps in UTC stay comparable when your server, your laptop, and your users are in different zones.
- The fix is one line (server timezone setting) plus a rule: never store local time, only convert at display.
What goes wrong when servers use local time?
The moment a second machine enters the picture, local time stops agreeing: a cron job that runs ‘at 2 AM local’ fires at a different instant on each server, logs from two servers can’t be ordered, and a database timestamp written in one zone is misinterpreted by another. Daylight saving time makes it worse — an hour repeats or vanishes, so a scheduler can fire twice or skip entirely. Every one of these is a real incident class that UTC eliminates at the source.
How do I switch a server to UTC?
Set the operating system’s timezone to UTC and configure the app to store and log UTC. Containers inherit the host’s zone unless you set TZ=UTC in the environment. Then enforce the rule in code: store UTC in the database, format it in UTC in logs, and convert to the user’s zone only at display time. If your app already stores local timestamps, migrate by interpreting them as UTC and re-writing — the longer they sit, the harder the migration.
# Check and set the server clock
timedatectl
# Local time: Sat 2026-08-16 02:15:33 UTC
# Universal time: Sat 2026-08-16 02:15:33 UTC
sudo timedatectl set-timezone UTC
# Verify: 'Local time' and 'Universal time' now read the sameWhat about displaying time to users?
UTC is the storage and logging format, never the display format. Convert to the user’s zone in the browser or at the API boundary using their timezone offset — JavaScript’s Intl API does this correctly, including daylight saving rules. Never subtract a fixed offset by hand; DST makes fixed offsets wrong for half the year. The mental model: UTC is the source of truth, local time is a view.
Where this bites vibecoders
AI assistants generate timestamps with whatever the platform default is, and vibecoders rarely notice until two services disagree — the cron job that runs at the wrong hour, or logs that can’t be ordered across a deploy. The assistant can’t see the server’s timezone, so ‘works on my machine’ extends to ‘works in my timezone’. A TZ=UTC convention plus a storage rule in the spec closes the gap permanently.
Where AI coding assistants get this wrong
- Generating code that stores local timestamps or formats with a hardcoded offset.
- Comparing timestamps across services without normalizing to UTC first.
- Scheduling jobs by local time without checking the server’s zone.
- Hand-rolling timezone math instead of using the platform’s timezone-aware datetime type.
Checklist
- Set every server and container to UTC (TZ=UTC).
- Store and log timestamps in UTC, with timezone info where supported.
- Convert to user-local time only at display, via the platform’s timezone API.
- Never hardcode offsets; daylight saving makes them wrong for months at a time.
FAQ
Is UTC the same as GMT?
Practically yes for everyday purposes: UTC is the atomic-clock standard and GMT is the solar-time zone that tracks it. No daylight saving applies to either. In code, treat them as the same thing and use UTC.
What if I only have one server and all my users are local?
It still pays to use UTC: logs become comparable with any future service, backups and exports sort correctly, and the server’s clock stays stable across DST changes. The cost of UTC is one config line; the cost of local time is an incident you can’t predict.
Related topics
- What Is a Cron Job (and Why Do They Fail Silently)?
- What Is the Twelve-Factor App Methodology?
- How to Set Up Automated Database Backups
- What Is Observability (and How Is It Different From Monitoring)?