Skip to content

Multi-Cloud Roadmap

CruzJS talks to infrastructure through logical bindings — sql, kv, blob, queue, llm, and a set of optional capabilities — rather than calling cloud SDKs directly. On Cloudflare those bindings resolve to D1, KV, R2, Queues, and Workers AI. The adapter layer is what lets a future target map the same logical bindings onto a different cloud’s native services, so application code never changes when the deployment target does.

A RuntimeAdapter provides platform-specific implementations for database, cache, queue, AI, and storage bindings. Cloudflare is implemented and shipping. The remaining adapters are roadmap items:

TargetAdapterRuntime TypeStatus
Cloudflare Workers/PagesCloudflareAdapterEdgeShipping
AWS Lambda + API GatewayAWSLambdaAdapterServerlessPlanned
AWS ECS FargateAWSFargateAdapterContainerPlanned
Google Cloud RunGCPCloudRunAdapterContainerPlanned
Google Cloud FunctionsGCPCloudFunctionsAdapterServerlessPlanned
Azure FunctionsAzureFunctionsAdapterServerlessPlanned
Azure Container AppsAzureContainerAppsAdapterContainerPlanned
DigitalOcean App PlatformDigitalOceanAppPlatformAdapterContainerPlanned
Docker / self-hostedDockerAdapterContainerPlanned
  • Edge — runs at the edge (Cloudflare Workers). Lowest latency, V8 isolate runtime.
  • Serverless — scale-to-zero functions (Lambda, Cloud Functions). waitUntil() must be flushed before the response returns.
  • Container — long-running processes (Fargate, Cloud Run, Docker). waitUntil() is fire-and-forget.

The abstraction the adapters implement. This is the design reference for the planned targets — Cloudflare is the only one wired end-to-end today.

interface RuntimeAdapter {
readonly name: string;
readonly type: 'edge' | 'serverless' | 'container';
init(context: unknown): Promise<void>;
getDatabase(): unknown;
getCache(namespace?: string): CacheBinding;
getQueue<T>(name: string): QueueBinding<T>;
getLocalQueue<T>(name: string): LocalQueueLike<T> | null;
getAI(): AIBinding | null;
getBinding<T>(name: string): T | null;
getStorageBucket(): unknown | null;
waitUntil(promise: Promise<unknown>): void;
get env(): Record<string, string | undefined>;
get diagnostics(): Record<string, unknown>;
clear(): void;
// Optional bindings — return null when unsupported; modules fall back to
// in-memory or no-op implementations.
getRateLimiter(): RateLimitAdapter | null;
getScheduler(): SchedulerAdapter | null;
getBroadcast(): BroadcastAdapter | null;
getSSEBackend(): SSEBackend | null;
getSearch(): SearchAdapter | null;
getSessionAdapter(): SessionAdapter | null;
getLogger(): LogAdapterBinding | null;
}

How each logical binding is intended to map onto each cloud’s native service. Only the Cloudflare column is implemented today.

BindingCloudflareAWS LambdaAWS FargateGCP Cloud RunGCP FunctionsAzure FunctionsAzure ContainersDigitalOceanDocker
DatabaseD1DynamoDB / RDSRDSCloud SQLCloud SQLCosmos DBCosmos DBManaged DBPostgreSQL
CacheKVElastiCacheElastiCacheMemorystoreMemorystoreRedis CacheRedis CacheRedisRedis
QueueQueuesSQSSQSPub/SubPub/SubService BusService BusBullMQ
AIWorkers AIBedrockBedrockVertex AIVertex AIOpenAIOpenAIOllama
StorageR2S3S3GCSGCSBlob StorageBlob StorageSpacesLocal/S3
Rate LimiterKVElastiCacheElastiCacheMemorystoreMemorystoreRedis CacheRedis CacheRedisRedis
SchedulerKVDynamoDBRedisMemorystoreMemorystoreRedis CacheRedis CacheRedisRedis
BroadcastKVElastiCacheElastiCacheMemorystoreMemorystoreRedis CacheRedis CacheRedisRedis
SSE BackendKVRedisRedisRedisRedisRedis
SearchFTS5 (D1)OpenSearchOpenSearchOpenSearch
SessionsKVDynamoDBRedisMemorystoreMemorystoreRedis CacheRedis CacheRedisRedis
LoggerConsole/LogpushCloudWatchCloudWatchCloud LoggingCloud LoggingApp InsightsApp Insightsstdout

The adapter field is optional in createCruzApp(). Without it, the framework uses CloudflareContext directly. The Cloudflare adapter is the only supported target:

import { CloudflareAdapter } from '@cruzjs/adapter-cloudflare';
export default createCruzApp({
schema,
modules: [/* your modules */],
adapter: new CloudflareAdapter(),
pages: () => import('virtual:react-router/server-build'),
});

See Adapter Setup to configure it.