Rethinking Serverless Series
This is the second blog of the series, Rethinking Serverless, which dives into Raindrop’s Services, Observers, and Actors . You can read up on the full series here:
Dev engineers who love serverless compute often highlight these three top reasons:
But there’s another major challenge that forces developers into complex workarounds: building applications that react to events and changes automatically.
Most applications need to respond to events: files uploaded to storage, messages arriving in queues, data changes triggering downstream processing. Traditional serverless platforms leave you with limited options—polling APIs on timers, setting up complex webhook systems, or building custom event routing infrastructure.
Polling wastes resources and creates delays. Webhooks require managing external endpoints and handling failures. Custom event systems add operational complexity that defeats the purpose of going serverless in the first place.
Observers in Raindrop are powerful components that let you execute code in response to changes in your resources automatically. Think of them as event listeners that trigger when specific conditions are met in your application—no polling, no complex setup, just clean reactive code.
Observers are the second pillar in Raindrop’s approach to modern serverless development:
Let’s dive into how Observers can be used to make your life easier.
Object observers watch for changes to objects in your buckets and execute code in response. They’re perfect for processing files after upload, generating thumbnails, extracting metadata, or triggering downstream workflows when data changes.
// in your raindrop.manifest file
application "demo" {
bucket "user-uploads" {}
observer "file-processor" {
source {
bucket = "user-uploads"
rule {
actions = ["PutObject", "CompleteMultipartUpload"]
}
}
}
}
// in your index.ts file
export default class extends Each<Body, Env> {
async process(message: observers.BucketEventNotification): Promise<void> {
console.log(`Bucket event message: ${JSON.stringify(message)}`);
}
}
Your observer automatically triggers whenever files are uploaded to your bucket. No polling, no webhooks to manage, no infrastructure to maintain.
Object observers can respond to various bucket events:
PutObject
, CopyObject
, CompleteMultipartUpload
DeleteObject
, LifecycleDeletion
This gives you fine-grained control over which events should trigger your processing logic.
Queue observers process messages as they arrive in queues. They’re the perfect solution for handling background jobs, sending notifications, processing payments, or any task that shouldn’t block your main application flow.
// in your raindrop.manifest file
queue "background-jobs" {}
observer "job-processor" {
source { queue = "background-jobs" }
}
// in your index.ts file
export default class extends Each<Body, Env> {
async process(message: Body): Promise<void> {
console.log(`Processing background job: ${JSON.stringify(message)}`);
// Handle email sending, image processing, data exports, etc.
}
}
Other services can add jobs to the queue, and your observer processes them asynchronously. The queue handles retries, dead letter queues, and scaling automatically.
With Observers, you can separate synchronous user-facing operations from asynchronous background processing. Your API responds quickly to users while heavy work happens in the background.
// in your raindrop.manifest file
application "photo-app" {
// Public API for uploads
service "api" { domain { cname = "photo-api" } }
// Storage for user photos
bucket "photos" {}
// Background processing
queue "photo-jobs" {}
observer "photo-processor" {
source { bucket = "photos" }
}
observer "job-processor" {
source { queue = "photo-jobs" }
}
}
Users upload photos through your API, which stores them in the bucket and immediately returns success. The photo-processor observer automatically generates thumbnails and metadata, while job-processor handles tasks like sending notifications or updating user profiles.
Traditional event-driven systems require message brokers, event schemas, consumer groups, and complex failure handling. With Observers, all of that is handled automatically. You focus on writing the processing logic, not managing the event infrastructure.
You get the benefits of event-driven architecture—independent scaling, ease of deployment, and paying for what you use only—without the operational overhead.
Observers solve the reactive programming challenge in serverless architectures, letting you build applications that respond to events naturally. But there’s still one piece missing: maintaining state across requests.
Part 3 - Actors (coming soon): Discover stateful serverless computing:
Together, Services, Observers, and Actors form a complete platform for building applications that were near impossible with traditional serverless architectures.
Ready to build reactive applications without the complexity? Check out the complete Observers documentation and start responding to events the way it should work.
In our final post, we’ll explore how Actors bring persistent state to serverless computing, completing the picture of what modern serverless development can be.
Ready to make your data smarter with your own AI agents? We’re offering:
✨ Free 2 million tokens and 10GB of storage per month
💰 Pay-as-you-go for additional tokens and storage
🎯 No egress fees
Want to explore costs first? Take a look at our pricing here. To get in contact with us or for more updates, join our Discord community.