Skip to content

Reference

Here is the surface in one place. Rust groups methods under accessors and takes option structs. Node and Python put methods directly on the client with plain arguments. Go uses methods on its Forge handle. Node and Python also expose native JSON handles from the main import (forge.queue<T>("emails"), forge.queue("emails")) so application payloads stay typed without a separate overlay.

import { ForgeClient } from "forgelib";
const forge = await ForgeClient.init(); // reads ./forge.toml
const forge2 = await ForgeClient.initFrom("path/forge.toml");

The memory test factories inject a manual clock and seeded, non-cryptographic entropy. Advancing time drives KV TTLs, sessions and tokens, delayed jobs, retry availability, rate-limit refill, and schedules without sleeping. Never use seeded entropy for production credentials.

const config = '[forge]\nmode = "memory"\nenvironment = "test"\n';
const forge = await ForgeClient.initMemoryForTesting(config, Date.UTC(2026, 0, 1), 42);
forge.advanceTestClock(60); // seconds

Rust’s testing::TestDatabase::new() creates and later drops one isolated PostgreSQL database using the maintenance URL in TEST_DATABASE_URL; integration tests never reuse an application database. The repository’s Node, Python, and Go conformance runners follow the same per-run isolation model. The CI integration job sets a sentinel that turns a missing database URL into failure rather than a skipped pass.

Operation Rust Node Python Go
Get kv().get kvGet kv_get KVGet
Set (TTL, NX, XX) kv().set kvSet kv_set KVSet
Get many kv().mget kvMget kv_mget KVMGet
Increment kv().incr kvIncr kv_incr KVIncr
Delete kv().delete kvDelete kv_delete KVDelete
Exists kv().exists kvExists kv_exists KVExists
Set TTL kv().expire kvExpire kv_expire KVExpire
Compare and swap kv().compare_and_swap kvCompareAndSwap kv_compare_and_swap KVCompareAndSwap
Prefix scan kv().scan kvScan, kvScanPage kv_scan, kv_scan_page KVScan
Operation Rust Node Python Go
Enqueue queue().enqueue queueEnqueue queue_enqueue Enqueue
Batch enqueue queue().enqueue_batch queueEnqueueBatch queue_enqueue_batch EnqueueBatch
Lease a job queue().dequeue queueDequeue queue_dequeue Dequeue
Batch lease queue().dequeue_batch queueDequeueBatch queue_dequeue_batch DequeueBatch
Ack queue().ack queueAck queue_ack Ack
Nack queue().nack queueNack queue_nack Nack
Extend the lease queue().heartbeat queueHeartbeat queue_heartbeat Heartbeat
Depth and oldest age queue().depth queueDepth queue_depth Depth
Pause / resume queue().pause, resume queuePause, queueResume queue_pause, queue_resume PauseQueue, ResumeQueue
Throughput stats queue().stats queueStats queue_stats QueueStats
Inspect dead letters queue().dead_letters queueDeadLetters queue_dead_letters DeadLetters
Redrive queue().redrive queueRedrive queue_redrive Redrive
Purge dry-run / confirmed queue().purge_dead_letters_* queuePurgeDeadLetters* queue_purge_dead_letters* PurgeDeadLetters*
Managed worker worker(name) worker(name, handler) worker(name, handler) RunWorker
Outbox relay pass run_outbox_once runOutboxOnce run_outbox_once RunOutboxOnce
Continuous outbox relay run_outbox_relay_until runOutboxRelay run_outbox_relay RunOutboxRelay
Operation Rust Node Python Go
Publish pubsub().publish pubsubPublish pubsub_publish Publish
Subscribe pubsub().subscribe pubsubSubscribe pubsub_subscribe Subscribe
Channel name pubsub().channel_for pubsubChannel pubsub_channel PubsubChannel
Operation Rust Node Python Go
Put blob().put blobPut, blobPutObject blob_put, blob_put_object BlobPut
Get blob().get blobGet blob_get BlobGet, BlobOpen
Head (metadata) blob().head blobHead blob_head BlobHead
Delete blob().delete blobDelete blob_delete BlobDelete
List blob().list blobList blob_list BlobList
Presign download blob().presign_download blobPresignDownload blob_presign_download BlobPresignDownload
Presign upload blob().presign_upload blobPresignUpload blob_presign_upload BlobPresignUpload
Operation Rust Node Python Go
Hash password auth().hash_password hashPassword hash_password HashPassword
Verify password auth().verify_password verifyPassword verify_password VerifyPassword
Needs rehash auth().needs_rehash needsRehash needs_rehash NeedsRehash
Create session auth().create_session createSession create_session CreateSession
Validate session auth().validate_session validateSession validate_session ValidateSession
Revoke session auth().revoke_session revokeSession revoke_session RevokeSession
Create API key auth().create_api_key createApiKey create_api_key CreateAPIKey
Verify API key auth().verify_api_key verifyApiKey verify_api_key VerifyAPIKey
Create one-time token auth().create_token createToken create_token CreateToken
Consume one-time token auth().consume_token consumeToken consume_token ConsumeToken
Operation Rust Node Python Go
Check and consume ratelimit().check, check_with rateLimitCheck rate_limit_check RateLimitCheck
Operation Rust Node Python Go
Cron schedule().cron scheduleCron schedule_cron ScheduleCron
One-off schedule().at scheduleAt schedule_at ScheduleAt
Cancel schedule().cancel scheduleCancel schedule_cancel ScheduleCancel
List schedule().list scheduleList schedule_list ScheduleList
Tick once run_scheduler_once runSchedulerOnce run_scheduler_once RunSchedulerOnce
Operation Rust Node Python Go
Get value config().get_raw configGet config_get ConfigGet
Set value config().set_raw configSet config_set ConfigSet
Delete value config().delete_raw configDelete config_delete ConfigDelete
Evaluate a flag config().flag flag flag Flag
Set a flag config().set_flag setFlagPercent, setFlagOn, setFlagOff, setFlagAllowList set_flag_percent, set_flag_on, set_flag_off, set_flag_allow_list SetFlag
Delete a flag config().delete_flag deleteFlag delete_flag DeleteFlag
Operation Rust Node Python Go
Backend capabilities backend_capabilities backendCapabilities backend_capabilities BackendCapabilities
Liveness is_live isLive is_live IsLive
Readiness probe probe probe probe Probe
Metrics snapshot metrics_snapshot metricsSnapshot metrics_snapshot MetricsSnapshot
Prometheus text render_prometheus renderPrometheus render_prometheus RenderPrometheus
Scheduler loop run_scheduler (interval) (interval) (interval)
Maintenance sweep maintain maintain maintain Maintain

These functions need no initialized client and add no transport or deployment behavior. See Integrations for their bounded profile and recipes.

Operation Rust Node Python Go
Encode CloudEvents 1.0 structured JSON CloudEvent::encode, encode_cloud_event encodeCloudEvent encode_cloud_event EncodeCloudEvent
Decode CloudEvents 1.0 structured JSON CloudEvent::decode, decode_cloud_event decodeCloudEvent decode_cloud_event DecodeCloudEvent
Import explicit environment aliases import_env_config importEnvConfig import_env_config ImportEnvConfig
Export canonical environment names export_env_config exportEnvConfig export_env_config ExportEnvConfig

Use raw methods for bytes and exact cross-language contracts. Use handles when the payload is app JSON and you want the name, codec, and type to stay together.

type SendEmail = { to: string; template: string };
const emails = forge.queue<SendEmail>("emails");
await emails.enqueue({ to: "a@b.c", template: "welcome" });
const profile = forge.kv<{ name: string }>("user:42:profile");
await profile.set({ name: "Ada" });
const events = forge.topic<{ type: "created"; userId: string }>("user.created");
await events.publish({ type: "created", userId: "42" });

A few methods return small records. The field names match the table; Node uses camelCase and times end in Ms.

  • Decision (rate limit): allowed, limit, remaining, resetAfterSeconds, retryAfterSeconds.
  • Job (queue): id, receipt, payload, attempt, maxAttempts, plus the queue and lease deadline.
  • QueueDepth: visible, inFlight, delayed.
  • BlobInfo (head): key, size, contentType, etag, lastModified, metadata.
  • BlobSummary (list): key, size, opaque etag, lastModified; use head for content type and user metadata.
  • ProxyPresign: url, method, key, expiresEpoch, maxBytes, signature, requiredHeaders.
  • NativePresign: url, method, expiresEpoch, requiredHeaders, constraints; native PUT has no portable size ceiling.
  • Session: userId, createdAt, expiresAt.
  • ApiKey (on create): id, secret (shown once), label, createdAt, optional expiresAt, scopes, metadata.
  • TokenConsumption: userId, bounded opaque payload; returned atomically once.
  • BackendInfo: primitive, provider, durable, caveats.

Every failure maps onto one of these. The retryable column says whether trying again might succeed.

Error Retryable Meaning
Config no Bad configuration. Only happens during init().
Unavailable yes A transient backend outage (timeout, dropped connection).
NotFound no The requested entity doesn’t exist.
Precondition no A condition failed: a CAS mismatch, a lost lease, an unknown receipt. Re-read state and decide. (A duplicate dedup_id is not an error — enqueue returns the existing job’s id.)
Limit no A size or quota limit was exceeded.
Invalid no A bad argument or malformed input.
Backend sometimes Anything else, carrying its own retryable flag.

In Rust these are variants of ForgeError with code(), is_retryable(), operation(), backend_id(), and a retained source chain. Node throws a structured ForgeError with code, retryable, operation, backend, safeMessage, and the normal message. Python raises typed subclasses of forgelib.ForgeError with the same fields. Go returns *forge.Error with the same stable metadata and an unwrapped local cause.

Oversized input is rejected with a Limit error rather than truncated.

Thing Limit
Key/value key 512 bytes
Key/value value 1 MiB
Queue payload 256 KiB
Blob object 50 MiB
Blob key 1024 bytes
Pub/sub payload ~7 KB, UTF-8
Config value 64 KiB
Password input 4096 bytes
Token purpose 255 bytes

Forge ships memory and PostgreSQL for every primitive, plus filesystem and S3-compatible storage for blob bytes. Rust may inject a custom primitive trait at compile time as an advanced extension. Other languages intentionally have no plugin loader or arbitrary backend injection.

let forge = forgelib::Forge::builder()
.kv(my_redis_kv) // kv runs on your backend; the rest stay on Postgres
.build()
.await?;

Forge’s API isn’t in any model’s training data, so a coding agent won’t know it cold. Install the companion skill and the agent learns which primitive fits which task and the idioms for each language before it writes Forge code.

Terminal window
npx skills add isala404/forge