Skip to main content

Data Types

ekoDB supports 16 comprehensive data types with flexible type enforcement per collection and per field.

Type Enforcement

  • Write-time validation: Types are checked when data is inserted or updated
  • Optional at key-value level: Key-value operations can be schema-less
  • Required at document level: Collections can enforce schemas
  • Dynamic inference: Types are automatically detected if not specified
  • Explicit specification: Define schemas via /api/collections/{collection} endpoint

Response Formats

ekoDB supports two response formats:

Typed Responses (Default)

Includes type metadata for strong typing:

{
"name": {
"type": "String",
"value": "Alice"
},
"age": {
"type": "Integer",
"value": 30
}
}

Benefits:

  • Type safety
  • Explicit type information
  • Better for strongly-typed languages

Non-Typed Responses

Traditional NoSQL format:

{
"name": "Alice",
"age": 30
}

Benefits:

  • Simpler JSON
  • Smaller payload size
  • Familiar format

Configuration: Set via /api/config endpoint or ekoDB App


Basic Types

String

UTF-8 encoded text data for names, descriptions, and general content.

{
"name": "Alice",
"email": "alice@example.com",
"description": "Software engineer"
}

Use Cases: Names, emails, descriptions, URLs, JSON strings


Integer

64-bit signed integers for whole numbers.

Range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

{
"age": 30,
"count": 1000,
"year": 2024
}

Use Cases: Counters, ages, quantities, IDs


Float

64-bit IEEE 754 floating-point numbers for decimal values.

{
"price": 29.99,
"temperature": 98.6,
"percentage": 0.85
}

Use Cases: Prices, measurements, percentages, scientific data

Precision Limitation

Floats have precision limitations. For financial calculations, use Decimal instead.


Boolean

Binary true/false values for logical operations.

{
"isActive": true,
"hasAccess": false,
"verified": true
}

Use Cases: Flags, toggles, status indicators


Producing a non-inferable type on write

ekoDB infers a field's type from the raw JSON you send: true/falseBoolean, a JSON string → String, a whole number → Integer, a fractional number → Float, an array → Array, an object → Object. The types below in Advanced Numeric, Temporal, and (for Set/Vector) Collection are not inferred from a raw value — a raw RFC 3339 string is stored as a String, a raw array as an Array, and so on. To store one of these, send the typed wrapper { "type": "<TypeName>", "value": <value> }.

One exception, via schema coercion: if the collection's schema declares a field as Number or Decimal, a raw numeric value is upgraded to that type. There is no string→DateTime/UUID/Decimal or array→Set/Vector coercion.

Advanced Numeric Types

Number

Flexible numeric type that holds either an integer or a float. A raw number is inferred as Integer or Float, so request Number explicitly with the { "type": "Number", "value": … } wrapper (or declare the field as Number in the schema, which coerces a raw number to Number):

{
"metric": { "type": "Number", "value": 42 }, // Number holding an integer
"average": { "type": "Number", "value": 42.5 } // Number holding a float
}

Use Cases: When you don't know if a value will be an integer or float

Benefits:

  • Automatic type detection
  • Seamless conversion
  • Flexible queries

Decimal

Arbitrary-precision decimal numbers that avoid floating-point rounding errors. The wrapper's value is a string (to preserve precision); a raw string is stored as String, so use the wrapper (or declare the field as Decimal in the schema, which coerces a raw numeric value to Decimal):

{
"balance": { "type": "Decimal", "value": "1234.56" },
"price": { "type": "Decimal", "value": "0.10" },
"total": { "type": "Decimal", "value": "999999.99" }
}

Use Cases:

  • Financial calculations (currency, accounting)
  • Scientific computations requiring exact precision
  • Any scenario where 0.1 + 0.2 must equal exactly 0.3

Why Decimal?

  • No binary floating-point approximation
  • Exact decimal representation
  • Precision-preserving internal storage

Temporal Types

DateTime

RFC 3339 formatted date-time values with timezone support. A raw RFC 3339 string is stored as a String; to store a true DateTime (which enables date math and range semantics), use the wrapper with an RFC 3339 string value:

{
"createdAt": { "type": "DateTime", "value": "2026-01-01T00:00:00Z" },
"updatedAt": { "type": "DateTime", "value": "2026-12-31T23:59:59+00:00" },
"scheduledFor": { "type": "DateTime", "value": "2025-06-15T14:30:00-05:00" }
}

Format: ISO 8601 / RFC 3339
Timezone: Always include timezone (Z for UTC or offset)

Use Cases: Timestamps, scheduling, time-series data


Duration

Time-span values. The Duration wrapper's value is an integer number of milliseconds (a raw string like "30s" is stored as a String, not a Duration):

{
"timeout": { "type": "Duration", "value": 30000 }, // 30 seconds
"interval": { "type": "Duration", "value": 300000 }, // 5 minutes
"ttl": { "type": "Duration", "value": 7200000 } // 2 hours
}
Human-readable durations are a separate feature

The shorthand forms "30s", "5m", "1h", "7d" are accepted by the key-value store's ttl field, which has its own duration parser — they are not the Duration field type, whose wrapper takes milliseconds.

Use Cases: TTL, timeouts, intervals, expiration


Collection Types

Array

Ordered lists of heterogeneous elements, preserving insertion order.

{
"tags": ["rust", "database", "nosql"],
"scores": [95, 87, 92, 88],
"mixed": ["text", 42, true, null]
}

Features:

  • Maintains order
  • Allows duplicates
  • Can contain different types
  • Supports nested arrays

Use Cases: Tags, lists, ordered data, multi-value fields


Set

Unordered collections of unique values with automatic deduplication. A raw array is stored as an Array, so use the wrapper to get a Set:

{
"uniqueTags": { "type": "Set", "value": ["rust", "database", "nosql"] },
"permissions": { "type": "Set", "value": ["read", "write", "delete"] }
}

Features:

  • Automatic deduplication
  • No guaranteed order
  • Fast membership testing
  • Unique values only

Use Cases: Unique tags, permissions, categories


Vector

Fixed-dimension numeric arrays optimized for embeddings and vector similarity search. A raw array is stored as an Array, so use the wrapper to get a Vector:

{
"embedding": { "type": "Vector", "value": [0.1, 0.2, 0.3, 0.4] },
"features": { "type": "Vector", "value": [1.5, 2.3, 0.8, 4.1] }
}

Features:

  • Optimized for similarity search
  • High-performance indexing for fast similarity search
  • Cosine, Euclidean, Dot Product metrics
  • Fixed dimensions per field

Use Cases:

  • AI/ML embeddings
  • Semantic search
  • Recommendation systems
  • Image/text similarity

Object

Nested documents/maps with key-value pairs for complex structured data.

{
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip": "94102"
},
"metadata": {
"source": "api",
"version": "1.0"
}
}

Features:

  • Nested structure
  • Flexible schema
  • Supports all types as values
  • Can be deeply nested

Use Cases: Nested data, complex structures, JSON documents


Specialized Types

UUID

Universally unique identifiers (RFC 4122) for globally unique record identification. A raw string is stored as a String, so use the wrapper to get a UUID:

{
"id": { "type": "UUID", "value": "550e8400-e29b-41d4-a716-446655440000" },
"userId": { "type": "UUID", "value": "6ba7b810-9dad-11d1-80b4-00c04fd430c8" }
}

Format: 8-4-4-4-12 hexadecimal digits

Use Cases: Unique identifiers, correlation IDs, distributed systems


Binary

Binary data for images, files, and other binary content. A raw string is stored as a String; use the wrapper with a base64-encoded string value to get Binary:

{
"image": { "type": "Binary", "value": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." },
"file": { "type": "Binary", "value": "SGVsbG8gV29ybGQh" }
}

Encoding: base64 string on write (the wrapper also accepts a [0-255] byte array); reads return a byte array
Storage: Efficient binary storage

Use Cases: Images, files, encrypted data, binary blobs


Bytes

Raw byte arrays for unencoded binary data storage. A raw array is stored as an Array, so use the wrapper with a [0-255] byte-value array to get Bytes:

{
"rawData": { "type": "Bytes", "value": [72, 101, 108, 108, 111] } // "Hello"
}

Format: Array of decimal byte values (0-255)

Use Cases: Raw binary data, protocol buffers, custom encodings


Null

Explicit null/empty values for optional fields.

{
"middleName": null,
"deletedAt": null,
"optionalField": null
}

Use Cases: Optional fields, missing data, explicit absence


Type Conversion

ekoDB automatically handles type conversions where safe:

Number Type Flexibility

// Number can match Integer or Float
{ "value": 42 } // Integer
{ "value": 42.5 } // Float

Automatic Coercion

  • Integer to Float (always safe, within f64's exact-integer range)
  • Integer to Decimal (lossless)
  • Float to Decimal (within Decimal's range)
  • Integer or Float to Number (automatic)

Schema Definition

Define schemas to enforce types when creating a collection:

POST /api/collections/users
Content-Type: application/json
Authorization: Bearer {ADMIN_TOKEN}

{
"fields": {
"name": { "type": "String", "required": true },
"age": { "type": "Number", "min": 0, "max": 150 },
"email": { "type": "String", "unique": true },
"balance": { "type": "Decimal" },
"tags": { "type": "Array" },
"metadata": { "type": "Object" }
}
}

Note: See Collections & Schemas for complete schema management documentation.


Best Practices

✅ Do

  • Use Decimal for financial data
  • Use DateTime with timezones
  • Use Vector for embeddings
  • Use Set for unique collections
  • Define schemas for production collections

❌ Don't

  • Use Float for money (use Decimal)
  • Store dates as strings (use DateTime)
  • Use Array when you need uniqueness (use Set)
  • Mix types inconsistently

Next Steps


Questions? Contact support@ekodb.io