PostgreSQL Data Types in KalamDB
KalamDB uses PostgreSQL-oriented SQL declarations and a shared logical type model for schemas, storage, routine signatures, and client metadata. Use PostgreSQL type names when defining application tables. TypeScript, Dart, and Rust SDKs access those same server columns; they do not define a separate SQL type system.
KalamDB implements these types in its own Rust/DataFusion/Arrow engine. This does not mean every PostgreSQL type, precision rule, or wire representation is identical. FILE and EMBEDDING(n) are KalamDB extensions.
PostgreSQL type names to use
| Value | SQL declaration | Notes |
|---|---|---|
| Boolean | BOOLEAN | BOOL is an alias |
| Signed integers | SMALLINT, INTEGER, BIGINT | INT aliases INTEGER |
| Approximate numbers | REAL, DOUBLE PRECISION | Explicit 32-bit / 64-bit choice |
| Exact decimals | NUMERIC(p,s) or DECIMAL(p,s) | Current stored precision is 1–38, with scale from 0 to precision |
| Text | TEXT | VARCHAR / CHAR map to text; do not infer PostgreSQL length/padding enforcement |
| Binary data | BYTEA | Maps to the internal Bytes payload; see PGWire limits below |
| JSON documents | JSON, JSONB | Distinct logical types; JSONB canonicalizes document representation |
| Date / time of day | DATE, TIME | Keep separate from an instant |
| Wall-clock date and time | TIMESTAMP | Without a time zone |
| Instant | TIMESTAMPTZ or TIMESTAMP WITH TIME ZONE | Distinct logical type from TIMESTAMP |
| UUID | UUID | UUID value rather than an arbitrary text ID |
| Arrays and named values | TEXT[], enums, composites, domains | See named types |
Older metadata and SDK descriptors may still say Int, Float, Double, Bytes, DateTime, or Decimal. These internal names are not a recommendation to write a separate KalamDB-specific scalar schema. Prefer INTEGER, REAL, DOUBLE PRECISION, BYTEA, TIMESTAMPTZ, and NUMERIC(p,s) in new SQL.
SQL types versus SDK values
The SQL declaration, the on-disk representation, and the language value returned by an SDK are separate layers. For example, a BIGINT column remains a 64-bit integer even when an HTTP/JSON client represents it as a string to avoid JavaScript precision loss. Live-query rows use the same column types as ordinary queries.
- TypeScript/React typed tables use
drizzle-orm/pg-corebuilders through@kalamdb/orm. Review the SQL-to-Drizzle mapping and generator limits. - Dart and Rust expose typed cell values and schema metadata. Convert with their Dart cell accessors or Rust cell accessors; a wrapper name is not a SQL type declaration.
FILEandEMBEDDING(n)require KalamDB-specific handling; importing PostgreSQL Drizzle builders does not turn them into PostgreSQL built-ins.
Current type compatibility limits
The current mapper limits stored decimals to precision 38 and nonnegative scale. It maps FLOAT to the 32-bit internal type; use REAL or DOUBLE PRECISION explicitly rather than assuming PostgreSQL’s FLOAT(p) rules. Unparameterized NUMERIC currently defaults to (38,10) rather than arbitrary precision.
The current PGWire result mapper reports decimal values as TEXT and rejects binary/BYTEA results. Accepting BYTEA in a table definition therefore does not establish a PostgreSQL binary-driver round trip. JSONB and TIMESTAMPTZ have distinct PostgreSQL wire descriptors. These are implementation limits, not alternative SQL names developers need to learn.
Range, multirange, and shell CREATE TYPE forms are rejected. Check the release compatibility boundaries when porting a schema. PostgreSQL’s data type reference describes the upstream types; KalamDB’s supported subset and transport limits are documented here.
Data types are independent from table types, but some types have table-type-specific behavior. FILE
columns are supported on USER and SHARED tables, and EMBEDDING(n) columns become most useful
with vector search. See /docs/server/architecture/table-types
for the table boundary.
Type Selection Flow
Quick Type Selection
Use this table when deciding a column type:
| You store… | Use | Why |
|---|---|---|
| Generated application IDs | BIGSERIAL | Familiar declaration for a 64-bit identifier |
| Small whole numbers (status, counters) | INT | Compact and fast |
| Large counters | BIGINT | Higher range |
| User-facing text | TEXT | Flexible string storage |
| True/false values | BOOLEAN | Clear semantics |
| Decimal money-like values | DECIMAL(p,s) | Exact precision |
| Timestamps | TIMESTAMP | Time-based queries and ordering |
| Dates only | DATE | Calendar values without time |
| Structured document payload | JSON | Nested object/array data |
| Vector embeddings | EMBEDDING(n) | Semantic retrieval and similarity search |
Common Types in Practice
Integer Types
- Prefer
INTfor bounded counts. - Prefer
BIGINTfor IDs and values that can grow large.
Text and Boolean
- Use
TEXTfor variable-length strings. - Use
BOOLEANinstead of0/1integers for feature flags and state.
Decimal Values
- Use
DECIMALfor exact arithmetic (pricing, balances, rates). - Pick precision/scale deliberately, e.g.
DECIMAL(12,2).
Time Types
- Use
TIMESTAMPfor event records and ordering. - Use
DATEwhen time-of-day is not needed.
JSON Payloads
- Use
JSONfor dynamic payloads and schema-flexible metadata. - Keep frequently filtered fields as typed top-level columns.
Embeddings for Vector Search
- Use
EMBEDDING(n)for fixed-size vector columns. - Pick
nto match the embedding model you generate in your app or worker. - Index the embedding column before using it for nearest-neighbor retrieval.
Named types (CREATE TYPE)
Use named composites and enums when several columns or a server function share the same shape. They persist as nested values — not as JSON fallbacks.
Creating a table also catalogs an implicit row type with the same name (app.users is both the table and the row type). Topics catalog an implicit payload type. Full syntax: CREATE TYPE. Use those names in server function signatures.
Type Conversion
Use explicit casts when moving between compatible types.
Prefer explicit conversion over relying on implicit casting in critical queries.
Nullability and Defaults
Use NOT NULL for required fields and DEFAULT for stable inserts.
Recommended Patterns
- IDs:
BIGSERIAL PRIMARY KEY - Created timestamps:
TIMESTAMP NOT NULL DEFAULT NOW() - Money/rates:
DECIMAL(not floating point) - Optional user text: nullable
TEXT - Real-time transient events:
STREAM+TTL_SECONDS
Related Docs
- /docs/server/architecture/table-types
- /docs/server/architecture/vector-search
- /docs/server/architecture/file-upload-datatype
- /docs/server/sql-reference/tables
- /docs/server/sql-reference/types
- /docs/server/sql-reference/indexes
- /docs/server/sql-reference/file-datatype
PostgreSQL type distinctions
NUMERIC(p, s) and DECIMAL(p, s) are exact decimal declarations. Choose precision and scale for the stored values; they are not interchangeable with floating point.
JSON and JSONB have distinct logical types. JSONB uses a canonical document representation; do not depend on input key order or whitespace surviving a round trip. TIMESTAMP is a wall-clock value without a time zone; TIMESTAMPTZ represents an instant. Use the latter for timestamps that cross time zones.
Arrays, enums, composites and domains share the logical type catalog used by SQL, storage, routine binding and client metadata. See named types and domains for examples and supported evolution. Custom FILE and EMBEDDING(N) remain KalamDB extensions rather than ordinary PostgreSQL built-ins.