Postgres Timestamp Vs Timestamptz [new] <OFFICIAL ✓>
If you change your session time zone to 'Asia/Tokyo' (UTC+9) and read the table:
| Column | What PostgreSQL stores internally | |--------|----------------------------------| | ts_native | 2025-04-14 14:00:00 (exact text, no zone info) | | ts_tz | A UTC timestamp: 2025-04-14 18:00:00+00 (because 2pm ET = 6pm UTC) | postgres timestamp vs timestamptz
-- Assume my session time zone is 'America/New_York' SET TIME ZONE 'America/New_York'; -- Create a test table CREATE TABLE time_test ( ts_native TIMESTAMP, -- without tz ts_tz TIMESTAMPTZ -- with tz ); If you change your session time zone to
-- Insert the same "local" value INSERT INTO time_test VALUES ('2025-04-14 14:00:00', '2025-04-14 14:00:00'); TIMESTAMPTZ does not save 'America/Chicago' or '+05:30'
If you have ever built an app that serves users across multiple time zones, you’ve likely woken up to a 3:00 AM page about "incorrect order dates" or "meetings showing up at the wrong hour."
# Django/ORM example from django.utils import timezone import datetime bad_time = datetime.datetime(2025, 4, 14, 14, 0, 0) GOOD: Aware datetime good_time = timezone.now() # includes UTC offset
Always use in your application code. Quick Decision Flowchart Is this a single, absolute moment in time? │ ├── YES (e.g., created_at, updated_at, event start time for global users) │ → Use TIMESTAMPTZ │ └── NO (e.g., "Every day at 9 AM" recurring alarm) → Use TIMESTAMP + store time zone separately in another column Pro Tip: TIMESTAMPTZ Does NOT Store the Time Zone This is the #1 misunderstanding. TIMESTAMPTZ does not save 'America/Chicago' or '+05:30' . It converts your input to UTC, stores UTC, and discards the original offset.