Skip to content

KvStore MAX_TTL (365d) rejects legitimate retention windows longer than a year #323

Description

@aram356

Problem

KvHandle::put_bytes_with_ttl validates TTL against a hard-coded cap:

// crates/edgezero-core/src/key_value_store.rs:378
pub const MAX_TTL: Duration = Duration::from_secs(365 * 24 * 60 * 60);

Any TTL above that is rejected. Retention windows longer than one year are common and legitimate, so apps that need them cannot write through KvHandle at all.

Why this bites

Named-store resolution is only reachable via KvRegistry::named(id) -> KvHandle. So an app that needs a named KV store must go through KvHandle — and there is no way to opt out of the validation, since KvHandle exposes no accessor for its inner store. An app with a >365d retention policy is therefore stuck: it can either have named stores or its required TTL, not both.

The failure mode is quiet. The write is rejected by validation, and apps commonly treat KV write failures as non-fatal, so records silently stop persisting. In our case it took a round-trip test to surface it — nothing in the logs or types made it obvious.

Ask

Raise or parameterize MAX_TTL so retention windows above 365 days are expressible. Options, roughly in order of preference:

  1. Make the cap configurable per store / per handle (e.g. a builder option), defaulting to today's value.
  2. Raise the constant — note that multi-year retention policies exist, so a modest bump only moves the wall.
  3. At minimum, expose the cap publicly and make an over-cap write a hard, typed error callers can distinguish, so it cannot be swallowed as a generic KV failure.

(1) or (3) would both be enough to unblock us; (3) alone at least makes the failure loud instead of silent.

Interim workaround (downstream)

We clamp the TTL to MAX_TTL with a warning log. It is fail-safe in our case — the record expires earlier than configured rather than not being written — but it does not honor the operator's configured retention. We would like to remove the clamp once this is addressed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions