SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Architecture / 4 MIN READ

Should an API serialize 64-bit IDs as JSON strings?

Use JSON strings for 64-bit identifiers when an API must survive JavaScript precision limits, cross-language consumers, and generated clients.

If an API exposes 64-bit identifiers to browsers, mixed-language backends, or generated clients, serialize those IDs as JSON strings. That is the safest default wire contract. JSON permits numbers, but interoperability is where things fail: common consumers, especially JavaScript, cannot represent every 64-bit integer exactly. Keep identifiers as opaque strings on the wire, keep real arithmetic fields numeric, and convert explicitly at service boundaries.

Why not send 64-bit IDs as JSON numbers?

The JSON specification in RFC 8259 defines a number type, but it does not guarantee that every implementation preserves arbitrary integer precision. It describes JSON as a portable text format, not a promise that all parsers handle large integers identically. In practice, many clients map JSON numbers to the host language’s default numeric type.

That becomes dangerous in JavaScript, where Number is an IEEE 754 double. Once an integer exceeds 2^53 - 1, exact representation is no longer guaranteed. An identifier is not a quantity to compute with; it is a token that must round-trip exactly. If exact round-trip matters, numeric JSON is the wrong contract for 64-bit IDs.

This is also why the Protobuf ProtoJSON format serializes int64, fixed64, and uint64 as decimal strings. That is a strong interoperability signal for API designers, especially if you rely on code generation across languages.

What does the failure look like in a browser client?

Suppose your service emits this JSON.

Prerequisite: a client that parses JSON numbers into JavaScript Number.

{"id":9223372036854775807}

A browser client runs:

const obj = JSON.parse('{"id":9223372036854775807}');
String(obj.id)

The client cannot preserve that integer exactly, so the value changes during parsing or re-serialization. At that point, cache keys, URL construction, equality checks, and follow-up API calls can all use the wrong identifier.

If the server instead sends:

{"id":"9223372036854775807"}

then JSON parsers preserve the identifier exactly as a string value. A Java client can convert it to long if needed. A JavaScript client can keep it as a string or turn it into BigInt deliberately. That explicit conversion is the important design boundary.

When should this contract apply?

Use string serialization for fields that are identifiers: database primary keys, order IDs, user IDs, event IDs, snowflakes, ULIDs stored numerically, or any opaque 64-bit reference.

Do not apply the same rule blindly to quantities. Counts, sizes, timestamps used for arithmetic, and measured values are usually better left as numbers if your clients can safely consume their range. The distinction is semantic:

  • identifiers must round-trip exactly
  • quantities may need numeric operations

A useful checklist is simple:

  • Will any consumer be JavaScript, JSON tooling, or generated SDKs? Use strings for 64-bit IDs.
  • Is the field an opaque identifier rather than a value to sum or compare numerically? Use strings.
  • Do you need stable round-trip behavior across languages? Use strings.
  • Is the field genuinely for arithmetic and safely bounded? A JSON number may be fine.

What are the tradeoffs?

The main cost is that some consumers must parse the string into a native 64-bit type explicitly. That is usually a good trade: you move conversion to a deliberate edge instead of letting parsers silently corrupt identifiers.

The advice does not matter as much in tightly controlled systems where every consumer uses arbitrary-precision integers and you own all serializers. Even there, strings are often the cleaner public API contract because they survive more tooling, logs, and generated clients.

Follow-up questions?

Should responses use strings if requests currently accept numbers?

Yes. A practical migration path is to accept both temporarily, document strings as the canonical format, and emit strings consistently. That matches the ProtoJSON guidance, which defines 64-bit integers as decimal strings in output while allowing parsers to accept either numbers or strings for those fields.

Should 32-bit IDs also be strings?

Not necessarily. This recommendation is specifically about 64-bit identifiers crossing language boundaries. If you expect growth, standardizing on strings early avoids a future breaking change.

Next step: choose one rule for your schema now—“all 64-bit identifiers are JSON strings”—and enforce it in serializers, OpenAPI examples, and SDK tests.

Reviewed: 2026-09-06.

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗