SDKs & Client Libraries
Production-ready clients for Node.js, Python, Go, and PHP. Shared resilience and worker patterns; the capability matrix below shows where the languages diverge (notably PHP gRPC streaming).
Node.js
Production ready v1.0.40
TypeScript-first · ESM / CommonJS
Python
Production ready v1.0.24
Pydantic models · sync & async
Go
Production ready v1.1.0
Idiomatic options · full streaming gRPC
PHP
Production ready v1.0.21
PHP 8.2+ · readonly DTOs · unary gRPC
Installation
npm install @spooled/sdk| SDK | Package | Published |
|---|---|---|
| Node.js | @spooled/sdk | 1.0.40 |
| Python | spooled | 1.0.24 |
| Go | spooled-sdk-go | v1.1.0 |
| PHP | spooled-cloud/spooled | 1.0.21 |
Install commands above resolve the latest published version. Pin explicitly in production when you need a known-good release.
Capability matrix
One place for parity and gaps. Cells use text and a glyph (not colour alone). Optional install extras are still “Yes” when the feature ships in the package.
| Capability | Node | Python | Go | PHP |
|---|---|---|---|---|
| HTTP auto-retries (exp. backoff + jitter) | Yes | Yes | Yes | Yes |
| Circuit breaker | Yes | Yes | Yes | Yes |
| Worker runtime | Yes | Yes | Yes | Yes |
| Realtime WebSocket Python: optional `spooled[realtime]`. PHP: needs `ratchet/pawl`. | Yes | Yes | Yes | Yes |
| Realtime SSE Python: optional `spooled[realtime]`. | Yes | Yes | Yes | Yes |
| gRPC unary client Python: optional `spooled[grpc]`. PHP: needs `ext-grpc`. | Yes | Yes | Yes | Yes |
| gRPC StreamJobs wrapper PHP has generated stubs only — not exposed on SpooledGrpcClient. | Yes | Yes | Yes | Not yet |
| gRPC ProcessJobs wrapper PHP has generated stubs only — not exposed on SpooledGrpcClient. | Yes | Yes | Yes | Not yet |
| Workflow DAGs | Yes | Yes | Yes | Yes |
| Webhook ingestion (GitHub / Stripe / custom) | Yes | Yes | Yes | Yes |
| Dual sync + async clients Python ships SpooledClient and AsyncSpooledClient. Others: one primary concurrency model. | Not yet | Yes | Not yet | Not yet |
PHP gap: public SpooledGrpcClient exposes unary queue/worker
methods only. Generated StreamJobs / ProcessJobs exist on the stub
client but are not wrapped — use Node, Python, or Go for streaming gRPC helpers.
Quick start — create a job
Same enqueue call in every language (or cURL):
curl -X POST https://api.spooled.cloud/api/v1/jobs \
-H "Authorization: Bearer sp_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"queue_name": "my-queue",
"payload": {
"event": "user.created",
"user_id": "usr_123",
"email": "alice@example.com"
},
"idempotency_key": "user-created-usr_123"
}'Node.js / TypeScript SDK
Production ready
TypeScript-first client with ESM/CommonJS builds, comprehensive types, worker runtime, and
full gRPC streaming helpers (streamJobs / processJobs).
Node.js — Core resources
Jobs
Create, list, claim, complete, fail, retry, cancel
Workers
Register, heartbeat, deregister, SpooledWorker class
Queues
List, get, stats, pause, resume, delete, configure
Schedules
Cron schedules with timezone support
Workflows
DAG execution with job dependencies
DLQ
Dead letter queue operations
Node.js — gRPC client
High-performance gRPC client. Hosted API quotas are enforced server-side and surfaced as typed/structured errors:
import { SpooledGrpcClient } from '@spooled/sdk';
const grpcClient = new SpooledGrpcClient({
address: 'grpc.spooled.cloud:443',
apiKey: process.env.SPOOLED_API_KEY!,
useTls: true,
});
await grpcClient.waitForReady();
// Register worker
const { workerId } = await grpcClient.workers.register({
queueName: 'emails',
hostname: 'worker-1',
maxConcurrency: 10,
});
// Dequeue jobs in batch
const { jobs } = await grpcClient.queue.dequeue({
queueName: 'emails',
workerId,
batchSize: 10,
});
// Process and complete (echo leaseId for lease fencing)
for (const job of jobs) {
await processJob(job);
await grpcClient.queue.complete({
jobId: job.id,
workerId,
leaseId: job.leaseId ?? undefined,
result: { success: true },
});
}
grpcClient.close(); Performance: gRPC is typically lower-latency than HTTP for high-throughput workers
Node.js — Documentation
Python SDK
Production ready
Sync and async clients, Pydantic models, decorator-based worker runtime, and optional gRPC /
realtime extras (pip install spooled[all]).
Python — Quick start
Create a job (from the SDK README / examples/basic_usage.py):
from spooled import SpooledClient
client = SpooledClient(api_key="sp_live_...")
# Create a job
result = client.jobs.create({
"queue_name": "emails",
"payload": {
"to": "user@example.com",
"subject": "Welcome!",
"template": "welcome_email",
},
"priority": 5,
})
print(f"Job created: {result.id}")
# Get job details
job = client.jobs.get(result.id)
print(f"Status: {job.status}")
client.close() Process jobs with the worker runtime:
from spooled import SpooledClient
from spooled.worker import SpooledWorker
client = SpooledClient(api_key="sp_live_...")
worker = SpooledWorker(client, queue_name="emails", concurrency=10)
@worker.process
def handle_job(ctx):
to = ctx.payload["to"]
subject = ctx.payload["subject"]
send_email(to, subject)
return {"sent": True}
worker.start() # blocking
Optional: pip install spooled[realtime] for WebSocket/SSE,
pip install spooled[grpc] for gRPC (includes stream_jobs /
process_jobs).
Python — Documentation
Go SDK
Production ready
Idiomatic functional options, context propagation, worker runtime, and public
StreamJobs / ProcessJobs wrappers. v1.1.0 is
source-breaking for gRPC enqueue: EnqueueRequest.MaxRetries /
TimeoutSeconds are *int32 — use grpc.Int32(3), not a
bare int.
Go — Quick start
package main
import (
"context"
"fmt"
"os"
"github.com/spooled-cloud/spooled-sdk-go/spooled"
"github.com/spooled-cloud/spooled-sdk-go/spooled/resources"
)
func ptr[T any](v T) *T { return &v }
func main() {
client, err := spooled.NewClient(spooled.WithAPIKey(os.Getenv("SPOOLED_API_KEY")))
if err != nil {
panic(err)
}
resp, err := client.Jobs().Create(context.Background(), &resources.CreateJobRequest{
QueueName: "my-queue",
Payload: map[string]any{"key": "value"},
IdempotencyKey: ptr("unique-key"),
MaxRetries: ptr(3),
})
if err != nil {
panic(err)
}
fmt.Printf("Created job: %s\n", resp.ID)
}Go — Documentation
PHP SDK
Production ready
PHP 8.2+ with readonly DTOs, PSR-compatible HTTP/logger, worker runtime, webhook ingestion,
and optional unary gRPC. No public StreamJobs / ProcessJobs wrappers
yet (see matrix).
PHP — Quick start
<?php
use Spooled\SpooledClient;
use Spooled\Config\ClientOptions;
$client = new SpooledClient(new ClientOptions(
apiKey: getenv('SPOOLED_API_KEY'),
));
$userId = 'usr_123';
// Create a job
$job = $client->jobs->create([
'queue' => 'email-notifications',
'payload' => [
'to' => 'user@example.com',
'subject' => 'Welcome!',
'template' => 'welcome',
],
'idempotencyKey' => "welcome-{$userId}",
'maxRetries' => 5,
]);
echo "Created job: {$job->id}\n";PHP — Documentation
Plan limits
The hosted API enforces tier-based quotas (SDKs surface the same 429 / quota
errors). Numbers match Limits and backend plans.rs:
| Tier | Active Jobs | Daily Jobs | Queues | Workers |
|---|---|---|---|---|
| Free | 10 | 1,000 | 2 | 1 |
| Starter | 500 | 10,000 | 10 | 5 |
| Pro | 5,000 | 100,000 | 50 | 25 |
| Enterprise | Unlimited | Unlimited | Unlimited | Unlimited |
See the Limits documentation for the full matrix (API keys, schedules, workflows, payload size, rate limits, retention).
Dashboard tip
Account → Usage
What to look for:
- Current usage vs plan limits
- Jobs created today
- Active workers and queues
Actions:
- Upgrade plan if approaching limits
- Monitor usage trends
Need help?