Blog · GraphQL

    Tutorial9 min read·Unix Calculator Editorial Team·Mar 22, 2026

    GraphQL Subscriptions with Real-Time Timestamps

    Quick answer: In GraphQL, represent timestamps as Int (Unix seconds) for compact payloads or String (RFC 3339) for human debugging. A custom DateTime scalar gives validation without leaking language-specific Date objects across the wire. Never promise subscription ordering by timestamp alone — add a monotonic sequence or cursor compound key.

    Choosing Your Timestamp Type in GraphQL Schema

    The schema is a contract. If mobile clients already store epoch milliseconds, exposing seconds without renaming fields will cause silent 1000× bugs. Pick one transport unit for all new fields and deprecate the legacy ones with explicit descriptions. For public APIs, ISO strings reduce onboarding friction; for high-rate ticks, ints win bandwidth and parsing cost.

    # Unix seconds — compact
    type Event {
      id: ID!
      createdAt: Int!
      updatedAt: Int!
    }
    
    # Custom scalar — enforce parsing in one place
    scalar DateTime
    
    type AuditRow {
      id: ID!
      recordedAt: DateTime!
    }

    Custom DateTime Scalar Implementation

    Apollo Server and GraphQL Yoga both let you coerce values at the boundary. The serialize step must be deterministic for the same instant — do not mix local tz formatting in serialize with UTC in parseValue unless you love bug reports from Australia.

    import { GraphQLScalarType, Kind } from 'graphql';
    
    export const DateTimeScalar = new GraphQLScalarType({
      name: 'DateTime',
      serialize(value) {
        if (value instanceof Date) return Math.floor(value.getTime() / 1000);
        if (typeof value === 'number') return value;
        throw new TypeError('DateTime cannot represent value');
      },
      parseValue(value) {
        if (typeof value === 'number') return new Date(value * 1000);
        if (typeof value === 'string') return new Date(value);
        throw new TypeError('DateTime parse error');
      },
      parseLiteral(ast) {
        if (ast.kind === Kind.INT) return new Date(parseInt(ast.value, 10) * 1000);
        if (ast.kind === Kind.STRING) return new Date(ast.value);
        return null;
      },
    });

    Real-Time Subscriptions with Timestamps

    Subscriptions multiplex many producers into one consumer socket. Stamp authoritative server time when the event enters the gateway, not when the database driver returns — those two instants diverge under CPU pressure. Emit both publishedAt and seq so UI code can merge partial reconnect buffers deterministically.

    type Subscription {
      priceQuotes(symbol: String!): PriceTick!
    }
    
    type PriceTick {
      symbol: String!
      price: Float!
      asOfSec: Int!
      seq: Int!
    }
    
    // Resolver sketch — async iterator fan-in
    async function* subscribeQuotes(symbol) {
      for await (const row of broker.watch(symbol)) {
        yield {
          priceQuotes: {
            ...row,
            asOfSec: Math.floor(Date.now() / 1000),
            seq: nextSeq(symbol),
          },
        };
      }
    }

    Cursor-Based Pagination Using Timestamps

    Relay cursors should encode (sort_value, id) tuples, not opaque offsets. When sorting by descending created_at, two rows can share the same millisecond — the tie-breaker prevents pages from dropping rows under load. Base64-JSON cursors are fine; just version them so you can migrate without breaking mobile caches.

    Avoiding Common GraphQL Timestamp Mistakes

    MistakeProblemFix
    Float epochClient parsers round unpredictablyUse Int seconds or String ISO
    Trusting client clockForged "created" timesStamp on server only
    Millis vs seconds driftOff-by-1000 bugsPrefix field names with unit
    Order by time aloneCollisions under burst insertsAdd ULID or bigint id tie-break

    Key takeaways

    • Custom scalars centralize coercion — stop repeating parse logic per resolver.
    • High-frequency feeds need compact numeric timestamps plus sequence numbers.
    • Cursors must be stable under duplicate sort keys.
    • Never use native JS Date directly in schema serialization layers.
    • Link to knowledge docs when onboarding partners on your time model.

    Written by Unix Calculator Editorial Team — Senior Unix/Linux Engineers. Last verified May 2026.

    Reference: GraphQL timestamps (knowledge base)

    Get the Unix Timestamp Cheatsheet

    One email. Instant cheatsheet. No drip sequence.

    Advertisement