Platform Bindings
Every Aerostack function receives six native bindings through its env parameter. These are not HTTP clients — they are in-process Cloudflare bindings with near-zero latency.
interface Env { DB: Database // Database (SQL, SQLite-compatible) CACHE: Cache // Cache (key-value with TTL) QUEUE: Queue // Queue (background jobs) AI: AI // AI — Multi-provider LLM VECTORIZE: VectorSearch // Vector Search (semantic similarity) STORAGE: Storage // Storage (object storage with CDN)}Database (env.DB)
Section titled “Database (env.DB)”Aerostack’s edge database is SQL-based (SQLite-compatible). Full SQL support, automatic replication, and zero-latency access from your function.
Query patterns
Section titled “Query patterns”// Single rowconst user = await env.DB .prepare('SELECT * FROM users WHERE id = ?') .bind(userId) .first()
// Multiple rowsconst { results } = await env.DB .prepare('SELECT * FROM users WHERE active = ? ORDER BY created_at DESC LIMIT ?') .bind(1, 50) .all()
// Insert with returningconst created = await env.DB .prepare('INSERT INTO users (email, name) VALUES (?, ?) RETURNING *') .bind(email, name) .first()
// Updateconst { meta } = await env.DB .prepare('UPDATE users SET name = ? WHERE id = ?') .bind(newName, userId) .run()console.log(`Rows changed: ${meta.changes}`)
// Deleteawait env.DB.prepare('DELETE FROM sessions WHERE expires_at < ?').bind(Date.now()).run()Batch operations
Section titled “Batch operations”Execute multiple statements in a single round trip. All statements run in an implicit transaction — if any fails, they all roll back.
const results = await env.DB.batch([ env.DB.prepare('INSERT INTO orders (user_id, total) VALUES (?, ?)').bind(userId, total), env.DB.prepare('UPDATE users SET order_count = order_count + 1 WHERE id = ?').bind(userId), env.DB.prepare('INSERT INTO audit_log (action, user_id) VALUES (?, ?)').bind('order_created', userId),])Typed results
Section titled “Typed results”interface User { id: number email: string name: string created_at: string}
const user = await env.DB .prepare('SELECT * FROM users WHERE id = ?') .bind(userId) .first<User>()// user is User | nullWhen to use: Structured data, relational queries, transactions, anything that needs ACID guarantees.
Cache (env.CACHE)
Section titled “Cache (env.CACHE)”Aerostack’s cache provides a globally distributed key-value store. Reads are fast everywhere (eventually consistent). Writes propagate globally within 60 seconds.
Basic operations
Section titled “Basic operations”// String valuesawait env.CACHE.put('user:123:profile', JSON.stringify(profile))const raw = await env.CACHE.get('user:123:profile')const profile = raw ? JSON.parse(raw) : null
// Typed get — parses JSON automaticallyconst profile = await env.CACHE.get('user:123:profile', 'json')
// Deleteawait env.CACHE.delete('user:123:profile')
// Check existence without reading the valueconst meta = await env.CACHE.getWithMetadata('user:123:profile')if (meta.value === null) { // Key does not exist}TTL (time-to-live)
Section titled “TTL (time-to-live)”// Expire after 1 hour (3600 seconds)await env.CACHE.put('session:abc', tokenData, { expirationTtl: 3600 })
// Expire at a specific timestamp (Unix seconds)const oneHourFromNow = Math.floor(Date.now() / 1000) + 3600await env.CACHE.put('session:abc', tokenData, { expiration: oneHourFromNow })Metadata
Section titled “Metadata”Attach metadata to a key without increasing the value size:
await env.CACHE.put('report:daily', reportJson, { expirationTtl: 86400, metadata: { generatedAt: Date.now(), version: 3 }})
const { value, metadata } = await env.CACHE.getWithMetadata('report:daily', 'json')console.log(`Report version: ${metadata.version}`)List keys
Section titled “List keys”// List all keys with a prefixconst { keys } = await env.CACHE.list({ prefix: 'user:123:' })for (const key of keys) { console.log(key.name, key.expiration)}Cache-aside pattern
Section titled “Cache-aside pattern”The most common caching strategy — check cache first, query DB on miss, populate cache:
async function getCachedUser(env: Env, userId: number) { const cacheKey = `user:${userId}`
// 1. Try cache const cached = await env.CACHE.get(cacheKey, 'json') if (cached) return cached
// 2. Query DB const user = await env.DB .prepare('SELECT * FROM users WHERE id = ?') .bind(userId) .first()
if (!user) return null
// 3. Populate cache (5 min TTL) await env.CACHE.put(cacheKey, JSON.stringify(user), { expirationTtl: 300 })
return user}When to use: Session tokens, computed results, rate limit counters, configuration, any read-heavy data that can tolerate eventual consistency.
Queue (env.QUEUE)
Section titled “Queue (env.QUEUE)”Aerostack’s queue provides reliable, at-least-once message delivery. Send messages from your fetch() handler and process them asynchronously in a queue() handler.
Sending messages
Section titled “Sending messages”export default { async fetch(request: Request, env: Env): Promise<Response> { // Send a single message await env.QUEUE.send({ type: 'send-email', to: 'user@example.com', subject: 'Welcome', body: 'Thanks for signing up.' })
// Send a batch of messages await env.QUEUE.sendBatch([ { body: { type: 'resize-image', key: 'uploads/photo1.jpg' } }, { body: { type: 'resize-image', key: 'uploads/photo2.jpg' } }, { body: { type: 'resize-image', key: 'uploads/photo3.jpg' } }, ])
return Response.json({ queued: true }) }}Processing messages
Section titled “Processing messages”Add a queue() handler to your function. Cloudflare delivers messages in batches:
export default { async fetch(request: Request, env: Env): Promise<Response> { // ... your HTTP handler },
async queue(batch: MessageBatch, env: Env): Promise<void> { for (const msg of batch.messages) { try { const job = msg.body as { type: string; [key: string]: unknown }
switch (job.type) { case 'send-email': await sendEmail(job.to as string, job.subject as string, job.body as string) break case 'resize-image': await resizeImage(env, job.key as string) break default: console.error(`Unknown job type: ${job.type}`) }
msg.ack() // Remove from queue } catch (err) { msg.retry() // Re-queue for retry } } }}Delayed messages
Section titled “Delayed messages”// Delay delivery by 60 secondsawait env.QUEUE.send( { type: 'reminder', userId: 123 }, { delaySeconds: 60 })When to use: Email sending, image processing, webhook fan-out, any work that should not block the HTTP response.
AI (env.AI)
Section titled “AI (env.AI)”Run LLM inference directly from your function. Supports multiple providers and models with a unified interface.
Text generation
Section titled “Text generation”// Basic completionconst response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain edge computing in one paragraph.' } ]})console.log(response.response)
// With parametersconst response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { messages: [{ role: 'user', content: 'Write a haiku about databases.' }], max_tokens: 100, temperature: 0.7})Streaming responses
Section titled “Streaming responses”const stream = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { messages: [{ role: 'user', content: 'Tell me a story.' }], stream: true})
return new Response(stream, { headers: { 'Content-Type': 'text/event-stream' }})Text embeddings
Section titled “Text embeddings”Generate vector embeddings for semantic search:
const embedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', { text: 'How do I deploy a function?'})// embedding.data[0] is a float array (768 dimensions for bge-base)Image classification
Section titled “Image classification”const imageBuffer = await env.STORAGE.get('photos/cat.jpg')const result = await env.AI.run('@cf/microsoft/resnet-50', { image: [...new Uint8Array(await imageBuffer.arrayBuffer())]})// result: [{ label: 'tabby cat', score: 0.95 }, ...]Text classification and summarization
Section titled “Text classification and summarization”// Summarizeconst summary = await env.AI.run('@cf/facebook/bart-large-cnn', { input_text: longArticle, max_length: 200})
// Classify sentimentconst sentiment = await env.AI.run('@cf/huggingface/distilbert-sst-2-int8', { text: 'This product is amazing!'})When to use: Text generation, summarization, classification, embeddings, image analysis — any ML inference that should run close to your data.
Vector Search (env.VECTORIZE)
Section titled “Vector Search (env.VECTORIZE)”Aerostack’s vector search provides native vector similarity search. Store embeddings and query them with sub-millisecond latency from your function.
Insert vectors
Section titled “Insert vectors”// Generate embedding, then store itconst embedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', { text: 'Aerostack functions run on Cloudflare Workers'})
await env.VECTORIZE.upsert([{ id: 'doc-123', values: embedding.data[0], metadata: { title: 'Functions Overview', category: 'docs', source: 'knowledge-base' }}])Query by similarity
Section titled “Query by similarity”// Embed the queryconst queryEmbedding = await env.AI.run('@cf/baai/bge-base-en-v1.5', { text: 'How do I deploy edge functions?'})
// Find the 5 most similar documentsconst results = await env.VECTORIZE.query(queryEmbedding.data[0], { topK: 5, returnMetadata: 'all'})
for (const match of results.matches) { console.log(`${match.id} — score: ${match.score}, title: ${match.metadata?.title}`)}Filter by metadata
Section titled “Filter by metadata”const results = await env.VECTORIZE.query(queryEmbedding.data[0], { topK: 10, returnMetadata: 'all', filter: { category: 'docs' }})Delete vectors
Section titled “Delete vectors”await env.VECTORIZE.deleteByIds(['doc-123', 'doc-456'])When to use: Semantic search, RAG (retrieval-augmented generation), recommendation engines, duplicate detection, any similarity-based lookup.
Storage (env.STORAGE)
Section titled “Storage (env.STORAGE)”Aerostack Storage provides S3-compatible object storage with zero egress fees. Store files, images, PDFs, or any binary data.
Upload objects
Section titled “Upload objects”// Store a file from a requestconst formData = await request.formData()const file = formData.get('file') as File
await env.STORAGE.put(`uploads/${file.name}`, file.stream(), { httpMetadata: { contentType: file.type }})
// Store generated contentconst report = JSON.stringify(analyticsData)await env.STORAGE.put('reports/daily.json', report, { httpMetadata: { contentType: 'application/json' }})Download objects
Section titled “Download objects”const object = await env.STORAGE.get('uploads/photo.jpg')
if (!object) { return new Response('Not found', { status: 404 })}
return new Response(object.body, { headers: { 'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream', 'Content-Length': String(object.size) }})Delete objects
Section titled “Delete objects”// Single deleteawait env.STORAGE.delete('uploads/old-file.pdf')
// Batch deleteawait env.STORAGE.delete(['temp/a.txt', 'temp/b.txt', 'temp/c.txt'])List objects
Section titled “List objects”const listed = await env.STORAGE.list({ prefix: 'uploads/', limit: 100 })
for (const object of listed.objects) { console.log(`${object.key} — ${object.size} bytes, uploaded ${object.uploaded}`)}
// Paginationif (listed.truncated) { const nextPage = await env.STORAGE.list({ prefix: 'uploads/', cursor: listed.cursor })}Presigned URLs and multipart uploads
Section titled “Presigned URLs and multipart uploads”// Create a multipart upload for large filesconst upload = await env.STORAGE.createMultipartUpload('videos/large.mp4', { httpMetadata: { contentType: 'video/mp4' }})
// Upload partsconst part1 = await upload.uploadPart(1, chunk1)const part2 = await upload.uploadPart(2, chunk2)
// Completeawait upload.complete([part1, part2])When to use: File uploads, image storage, document processing, backups, serving static assets, any binary data.
Quick Reference
Section titled “Quick Reference”| Binding | Type | Access | Best For |
|---|---|---|---|
env.DB | Database | env.DB.prepare().bind().all() | Structured data, transactions |
env.CACHE | Cache | env.CACHE.get() / .put() | Hot data, sessions, counters |
env.QUEUE | Queue | env.QUEUE.send() | Background jobs, async work |
env.AI | Ai | env.AI.run(model, input) | LLM, embeddings, classification |
env.VECTORIZE | VectorSearch | env.VECTORIZE.query() | Semantic search, RAG |
env.STORAGE | Storage | env.STORAGE.put() / .get() | Files, images, binary data |