Skip to content

Valkey Factories

Factory functions for the Hyperspike Valkey operator with built-in readiness evaluation. Manage Valkey clusters as Kubernetes-native resources.

The integration provisions Valkey infrastructure. Application data-plane behavior—commands, Streams consumer groups, acknowledgements, retries, and dead-letter policy—belongs in the application or framework using a Valkey client, not in TypeKro.

Import

typescript
// Import specific functions (recommended)
import { valkey } from 'typekro/valkey';

// Or namespace import
import * as valkeyModule from 'typekro/valkey';

Quick Example

typescript
import { valkey } from 'typekro/valkey';

const cache = valkey({
  name: 'app-cache',
  namespace: 'default',
  spec: {
    shards: 3,
    replicas: 1,
    volumePermissions: true,
    storage: {
      spec: {
        storageClassName: 'gp3',
        resources: { requests: { storage: '10Gi' } },
      },
    },
    resources: {
      requests: { cpu: '250m', memory: '512Mi' },
      limits: { cpu: '1', memory: '2Gi' },
    },
    prometheus: true,
  },
  id: 'appCache',
});

Available Factories

FactoryKindScopeDescription
valkeyValkeyNamespaceValkey cluster (sharded with optional replicas)
valkeyHelmRepositoryHelmRepositoryNamespaceOCI Helm registry for the operator
valkeyHelmReleaseHelmReleaseNamespaceOperator installation via Helm
valkeyBootstrap / valkeyOperatorInstallationCompositionCluster infrastructureComplete, explicitly owned operator installation
valkeyHelmRepositoryBootstrapCompositionCluster singletonShared OCI repository owner

valkey()

Creates a Valkey cluster managed by the Hyperspike operator.

typescript
const cache = valkey({
  name: 'prod-cache',
  namespace: 'caching',
  spec: {
    // Cluster topology
    shards: 3,              // Number of primary nodes (default: 3)
    replicas: 1,            // Replicas per shard (default: 0)

    // Storage
    volumePermissions: true,
    storage: {
      spec: {
        storageClassName: 'gp3',
        resources: { requests: { storage: '50Gi' } },
      },
    },

    // Resources
    resources: {
      requests: { cpu: '500m', memory: '1Gi' },
      limits: { cpu: '2', memory: '4Gi' },
    },

    // Security
    tls: true,
    certIssuer: 'letsencrypt-prod',
    certIssuerType: 'ClusterIssuer',
    anonymousAuth: false,
    servicePassword: { name: 'valkey-secret', key: 'password' },

    // Monitoring
    prometheus: true,
    serviceMonitor: true,
    prometheusLabels: { prometheus: 'kube-prometheus' },

    // External access via Envoy proxy
    externalAccess: {
      enabled: true,
      type: 'Proxy',
      proxy: {
        replicas: 2,
        hostname: 'valkey.example.com',
      },
    },

    // Scheduling
    nodeSelector: { 'node-type': 'cache' },
    tolerations: [{
      key: 'dedicated',
      operator: 'Equal',
      value: 'cache',
      effect: 'NoSchedule',
    }],
  },
  id: 'prodCache',
});

Hyperspike replica behavior

Hyperspike v0.0.61 documents that replicas currently creates additional primary nodes rather than replicas. Track upstream issue #186 before relying on this field for high availability. This is especially important for durable Valkey Streams queues.

Valkey Readiness

The readiness evaluator checks the Hyperspike status model:

StateReadyReason
status.ready: truetrueReady
status.ready: false with conditionfalseCondition reason (e.g., ShardsNotReady)
status.ready: false without conditionfalseNotReady
No ready fieldFalls back to condition-based evaluation
Missing statusfalseStatusMissing

External Access Modes

  • Proxy (default) — Envoy proxy for external connections with optional TLS
  • LoadBalancer — Kubernetes LoadBalancer service per shard

Bootstrap Composition

Install the Hyperspike Valkey operator via Helm:

typescript
import { valkeyBootstrap } from 'typekro/valkey';

// 'kro' = KRO mode — creates a ResourceGraphDefinition for continuous reconciliation
// 'direct' = Direct mode — applies resources immediately without KRO controller
const factory = valkeyBootstrap.factory('kro', {
  namespace: 'valkey-operator-system',  // Where the operator pods run
  waitForReady: true,
});

await factory.deploy({
  name: 'valkey-operator',
  namespace: 'valkey-operator-system',  // Owned child: operator pods run here
  values: {
    nodeSelector: { 'kubernetes.io/os': 'linux' },
  },
});

valkeyBootstrap creates and owns the operator namespace as a graph child. If it stayed a graph child, KRO would delete that namespace when the instance is deleted — potentially deleting the instance before KRO clears its finalizer and deadlocking namespace termination. TypeKro therefore auto-detects the ownership and hoists the owned Namespace out of the RGD graph, emitting it as a retained resource created outside the graph (deps-first); the instance CR stays in its natural namespace. Direct mode has no KRO custom-resource finalizer and is unaffected.

values is the raw Helm passthrough and merges last. The older customValues field remains as a deprecated compatibility alias; when both are present, values wins. The Flux OCI HelmRepository is owned by the complete bootstrap and defaults to the operator namespace. Custom repositoryName, repositoryNamespace, and repositoryUrl values are propagated to the HelmRelease source reference. The official chart remains the sole owner of its cluster-wide RBAC; TypeKro does not duplicate those resources.

The bootstrap has an explicit owner lifecycle: deleting its KRO instance uninstalls the operator. Application compositions that share one cluster operator should wrap valkeyBootstrap with TypeKro's singleton() using concrete, graph-authoring-time settings. Deleting an application then removes only the singleton reference, not the operator owner.

Bootstrap Status

typescript
instance.status.ready    // boolean — operator is running
instance.status.phase    // 'Ready' | 'Installing' | 'Failed'
instance.status.failed   // boolean — true if Ready condition is explicitly False
instance.status.version  // deployment-time version; default is normalized to v0.0.61

If failed is true, check the HelmRelease conditions directly for controller-specific failure details.

Usage in Compositions

typescript
import { type } from 'arktype';
import { kubernetesComposition } from 'typekro';
import { Deployment, Service } from 'typekro/simple';
import { valkey } from 'typekro/valkey';

const AppWithCache = kubernetesComposition({
  name: 'app-with-cache',
  kind: 'AppWithCache',
  spec: type({ name: 'string', image: 'string' }),
  status: type({ ready: 'boolean', cacheReady: 'boolean' }),
}, (spec) => {
  const cache = valkey({
    id: 'cache',
    name: `${spec.name}-cache`,
    spec: { shards: 3, volumePermissions: true },
  });

  const deploy = Deployment({
    id: 'app',
    name: spec.name,
    image: spec.image,
    env: {
      VALKEY_HOST: `${spec.name}-cache`,
      VALKEY_PORT: '6379',
    },
  });

  return {
    ready: deploy.status.readyReplicas > 0,
    cacheReady: cache.status.ready,
  };
});

Prerequisites

The Hyperspike Valkey operator must be installed. Use the valkeyBootstrap composition or install manually:

bash
LATEST=$(curl -s https://api.github.com/repos/hyperspike/valkey-operator/releases/latest | jq -cr .tag_name)
helm install valkey-operator \
  --namespace valkey-operator-system \
  --create-namespace \
  oci://ghcr.io/hyperspike/valkey-operator \
  --version ${LATEST}-chart

For TLS support, cert-manager must be installed with an appropriate certificate issuer.

Valkey Streams queues

This factory is suitable for provisioning the Valkey service behind an application queue, including persistent storage, authentication, TLS, resource limits, and scheduling. TypeKro intentionally does not expose XADD, consumer-group, acknowledgement, retry, or dead-letter APIs. Those semantics should be implemented by the application layer using a Valkey-compatible client.

Hyperspike v0.0.61 is not a durable queue provider. Its generated valkey.conf enables periodic RDB snapshots but sets appendonly no, and the CRD does not expose a server-config override. A pod failure can therefore lose writes since the latest snapshot. TypeKro's live integration verifies ordinary commands and Streams plus explicit-RDB restart recovery, but it does not claim AOF or queue-grade durability. Use this provider for caches and workloads that accept that recovery point; use a configurable Valkey provider (or an upstream operator release with AOF configuration) before backing an authoritative queue.

The operator-generated password Secret uses the Valkey resource name and the password key when anonymousAuth is false and servicePassword is omitted, per the v0.0.61 CRD contract.

Next Steps

Released under the Apache 2.0 License.