Datastores
Your app never picks a database. It declares a capability — “I need a relational database” — and Zhenfy One provisions one, isolates it to your project, and injects its connection details as environment variables. Which engine backs each capability is our choice, and it is the part that can change.
What each capability runs on today
This table is the current answer, not a contract. The capability and the environment variables are the contract; the engine column can change without your app changing.
| Capability | Engine today | Env contract | Reach for it when |
|---|---|---|---|
| relational database | PostgreSQL | POSTGRES_* | the default for anything you need to keep |
| cache | Valkey (Redis API) | CACHE_* | sessions, counters, rate limits — never the source of truth |
| work queue | Valkey Streams | QUEUE_* | decoupling a slow job from a request |
| event stream | Kafka | KAFKA_* | replayable, ordered, multi-consumer events |
| search index | OpenSearch | SEARCH_* | relevance ranking and faceting beyond Postgres full-text |
| analytics store | ClickHouse | OLAP_* | aggregation over ~100M+ rows |
| object storage | Amazon S3 | BLOB_* | files, images, uploads |
Your code stays portable
Nothing Zhenfy-specific goes into your repository. Your app imports the ordinary driver for the engine, reads the documented environment variables, and owns its own schema — there is no SDK to import and no platform package to depend on. A generated Node app that uses a relational database contains roughly this, and nothing else:
import { Pool } from 'pg';
const pool = new Pool({ connectionString: process.env.POSTGRES_URL });Point those variables at any PostgreSQL and the same code runs unchanged — on your laptop, on another host, or anywhere you take the repository.
Where the declaration lives
The request for a store is pipeline metadata, not source code, which is what keeps the repository self-contained. It looks like this:
[{"kind": "database", "name": "main"},
{"kind": "cache", "name": "sessions"}]Note that it names a kind, never an engine. You can see what your project ended up with under the Admin tab, and the Architecture section of a build’s readout reports the stores your app can actually reach.
Isolation and durability
- Each project gets its own database, its own role, and its own key/topic/index prefix on a shared engine.
- Beta and production get separate stores, so a beta experiment cannot touch production data.
- Data written to a declared store survives restarts, redeploys, and promotion to production.
- An app that declares no store keeps its data on the container’s disk, which is erased on every restart.
- Deleting a project deletes its stores and their contents.