NeedUseAvoidPrimary keyBIGINT GENERATED ALWAYS AS IDENTITY``SERIAL, BIGSERIALTimestampsTIMESTAMPTZ``TIMESTAMP (loses timezone)TextTEXT``VARCHAR(n) unless constraint neededMoneyNUMERIC(precision, scale)``MONEY, FLOATBooleanBOOLEAN with NOT NULL DEFAULTnullable booleansJSONJSONB``JSON (no indexing), text JSONUUIDgen_random_uuid() (PG13+)uuid-ossp extensionIP addressesINET / CIDRtextRangesTSTZRANGE, INT4RANGE, etc.pair of columnsRaw bytes (verbatim payload)BYTEA``JSONB, TEXT (both re-encode)
A spec that says "log the raw response" is asking for byte fidelity, and no text type provides it. JSONB reparses: it drops insignificant whitespace, sorts object keys, keeps only the last of duplicate keys, and rewrites numbers out of exponent notation ( 1e0 -> 1; trailing zeros in 1.00 do survive, so "all numeric forms collapse" overstates it). A non-JSON body cannot be stored at all and usually lands as NULL. TEXT rejects a NUL byte and any sequence invalid in the database encoding, so a binary or mis-encoded body errors instead of storing. Persist the bytes in BYTEA with the content type beside them, and add a parsed JSONB column separately when queries need one. Reading the column type as proof the body is kept is the review error.
Start changed-query inspection with EXPLAIN. Run EXPLAIN (ANALYZE, BUFFERS) with representative data only when executing the query and its side effects is authorized and safe. For writes, prefer disposable data; use a transaction followed by rollback only when all relevant effects are transactional. Investigate unexpected sequential scans and compare actual costs; accept a sequential scan when reading much of a table is cheaper than using an index. Confirm no unindexed FK columns before declaring done.
Read the relevant reference before implementing or reviewing the matching behavior:
Existing specialized references, when the corresponding topic applies: