
Alibaba Cloud Full Stack (8): Serverless — Function Compute and EventBridge
Go serverless on Alibaba Cloud: Function Compute triggers, runtimes, cold starts, and pricing. EventBridge for event routing. API Gateway integration. Build an event-driven image processing pipeline.
The first time I saw a Function Compute bill that was 0.03 CNY for handling 10,000 requests, I started rethinking my entire architecture. I had been running a 2-vCPU ECS instance 24/7 to serve an API that processed maybe 200 requests per hour, paying around 490 CNY/month. The same workload on Function Compute cost under 5 CNY/month. Not 5 CNY per day — 5 CNY per month. The math was so lopsided that I spent the next weekend migrating everything that did not need a persistent process off ECS and onto functions.
Serverless does not mean there are no servers. It means you stop thinking about servers. You write a function, you define what triggers it, and the platform handles provisioning, scaling, patching, and decommissioning. You pay only for the milliseconds your code actually runs. No traffic, no charge. A million requests in five minutes, a million function instances spin up. You never touch a capacity slider.
This article covers the two serverless building blocks on Alibaba Cloud: Function Compute (the execution engine) and EventBridge (the event routing layer). By the end, we will build a complete event-driven image processing pipeline that resizes, watermarks, and generates thumbnails — triggered automatically when files land in OSS.
When serverless makes sense (and when it doesn’t)#
Serverless is not a universal solution. It is a tool with a specific sweet spot, and understanding that sweet spot upfront saves you from a painful migration back to ECS three months later.
Good fits for serverless#
| Use case | Why it works | Example |
|---|---|---|
| Event processing | Naturally stateless, triggered by external events | Process OSS uploads, parse SLS logs |
| Webhooks | Infrequent, unpredictable traffic | GitHub webhook handler, payment callbacks |
| Scheduled jobs | Run once per hour/day, idle the rest | Daily report generation, data cleanup |
| API backends with bursty traffic | Scale-to-zero between bursts saves money | Marketing campaign API, seasonal e-commerce |
| Data transformation | Short-lived, CPU-bound, embarrassingly parallel | ETL pipelines, format conversion |
| Chatbot backends | Request-response pattern, variable load | DingTalk bot, Slack integration |
Bad fits for serverless#
| Use case | Why it fails | Better alternative |
|---|---|---|
| Long-running processes (>15 min) | FC has a 15-minute execution timeout | ECS, Container Service (ACK) |
| GPU workloads | No GPU support in FC | ECS GPU instances, PAI-EAS |
| Low-latency requirements (<10ms) | Cold starts add 100ms-2s | ECS with persistent process |
| WebSocket / persistent connections | Functions are request-response | ECS, ALB with sticky sessions |
| High steady-state throughput | Continuous execution is cheaper on ECS | ECS with reserved instances |
| Large in-memory state | Functions are stateless, max 3 GiB memory | ECS, Redis |

Before comparing prices, line up the three compute primitives side by side. FC, SAE, and ECS each occupy a distinct point on the granularity / lifecycle spectrum, and most architecture mistakes I see come from picking the wrong one for the workload.
The cost crossover point#
The question everyone asks: at what traffic level does ECS become cheaper than Function Compute?
Here is the math for a Python function with 512 MiB memory, 200ms average execution time:
| Monthly requests | FC cost (CNY) | ECS equivalent (CNY) | Winner |
|---|---|---|---|
| 10,000 | ~0.03 | ~490 (c7.large) | FC by 16,000x |
| 100,000 | ~0.30 | ~490 | FC by 1,600x |
| 1,000,000 | ~3.00 | ~490 | FC by 160x |
| 10,000,000 | ~30 | ~490 | FC by 16x |
| 100,000,000 | ~300 | ~490 | FC |
| 500,000,000 | ~1,500 | ~490 | ECS |
| 1,000,000,000 | ~3,000 | ~490 | ECS by 6x |
The crossover happens around 200-300 million requests per month for this configuration. Below that, Function Compute wins decisively. Above that, a dedicated ECS instance is cheaper — but you also need to handle scaling, patching, and availability yourself.
My rule of thumb: If your function averages fewer than 100 requests per second sustained (roughly 250 million/month), serverless is almost certainly cheaper and operationally simpler. If you consistently exceed that, evaluate ECS or a container solution.
Function Compute (FC) fundamentals#
Function Compute is Alibaba Cloud’s serverless execution service. The AWS equivalent is Lambda. The core concepts map directly:

| FC concept | What it is | AWS equivalent |
|---|---|---|
| Service | A logical grouping of related functions. Shares VPC config, log config, NAS mount, and role. | (No direct equivalent; Lambda uses tags/prefixes) |
| Function | The unit of execution. Your code + configuration. | Lambda function |
| Trigger | An event source that invokes the function. | Event source mapping / trigger |
| Layer | Shared dependencies packaged separately from function code. | Lambda layer |
| Custom domain | Map your own domain to HTTP-triggered functions. | API Gateway custom domain |
| Alias / Version | Immutable snapshots with traffic-shifting aliases. | Lambda versions and aliases |
The execution model#
When a request arrives, FC does the following:
- Check for a warm instance. If a function instance from a recent invocation is still alive (kept warm for ~5-15 minutes), route the request there. No cold start.
- Cold start (if needed). Download the code package, initialize the runtime, run your initialization code (module-level imports, DB connection pools). This takes 100ms to 2s depending on runtime and package size.
- Execute the handler. Run your function with the event payload. You are billed from this point.
- Return the response. The instance stays warm for subsequent requests.
Key limits to know:
| Limit | Value |
|---|---|
| Max execution time | 15 minutes (86,400s for async invocation) |
| Max memory | 32 GiB |
| Max code package (direct upload) | 100 MiB (compressed) |
| Max code package (OSS reference) | 500 MiB (uncompressed) |
| Max layers per function | 5 |
| Max concurrent instances (default) | 300 per function |
| Max payload (sync) | 32 MiB |
| Max payload (async) | 128 KiB |
Temp disk (/tmp) | 10 GiB |

The gap between the warm path and the cold path is the entire performance story of serverless. The warm path costs a few milliseconds; the cold path runs four extra steps before your handler even starts.
Runtimes#
FC supports these managed runtimes:
| Runtime | Versions | Cold start (typical) | Notes |
|---|---|---|---|
| Python | 3.9, 3.10 | 200-400ms | Most popular. Great ecosystem. |
| Node.js | 14, 16, 18 | 150-300ms | Fast cold start. Good for API backends. |
| Java | 8, 11, 17 | 1-3s | Slowest cold start. Use GraalVM or SnapStart. |
| Go | 1.x (custom runtime) | 50-150ms | Fastest. Single binary, no runtime init. |
| PHP | 7.2 | 200-400ms | Legacy support. |
| C# | .NET Core 6 | 500ms-1s | Moderate. |
| Custom Runtime | Any (Docker) | Varies | Full control. For ML models, system libs. |
| Custom Container | Any Docker image | 1-10s | Largest packages. Requires image pull. |
If cold start matters to you: Go is the fastest runtime by a wide margin because functions compile to a single static binary with no runtime initialization. Python is the practical sweet spot — moderate cold start, massive library ecosystem, easy to write. Java should be your last choice for latency-sensitive functions unless you use GraalVM native compilation.
Writing your first function#
Let’s build a function from scratch. We will use Python 3.10 and the Serverless Devs (s) CLI, which is the standard toolchain for FC development.
Install Serverless Devs#
| |
Project structure#
| |
The handler#
Here is the simplest possible function — an HTTP-triggered hello world:
| |
Let’s break down the handler signature:
event: The input payload. For HTTP triggers, this is the HTTP request body as bytes. For OSS triggers, it is a JSON object describing the uploaded file. The shape depends on the trigger type.context: A rich object containing the request ID (for log correlation), function metadata (name, memory, timeout), service metadata, credentials (temporary STS credentials if your function needs to call other Alibaba Cloud APIs), and region information.- Return value: For HTTP triggers, return a dict with
statusCode,headers, andbody. For non-HTTP triggers, you can return any JSON-serializable value.
The Serverless Devs configuration#
| |
Deploy and test#
| |
Test it with curl:
| |
Viewing logs#
FC sends all print() and logging output to Simple Log Service (SLS). You can view logs in the FC console, or query them via CLI:
| |
Triggers: what invokes your function#
Triggers are what make serverless event-driven rather than just “cheap hosting.” Each trigger type connects your function to a different event source. Here is every trigger type with configuration examples.

HTTP trigger#
The simplest trigger. Your function gets an HTTP endpoint.
| |
The function receives the full HTTP request and returns an HTTP response. This is the foundation for building REST APIs on Function Compute.
OSS trigger#
Fires when objects are created, modified, or deleted in an OSS bucket. This is the backbone of most serverless data pipelines.
| |
The event payload looks like this:
| |
OSS, the storage layer for our pipeline, is covered in detail in Part 4 .
Timer trigger (cron)#
Run functions on a schedule. Uses cron expressions or rate expressions.
| |
Timer triggers are the serverless replacement for crontab. No more keeping a dedicated ECS instance alive just to run a script once a day.
SLS trigger (log events)#
Process log entries from Simple Log Service in near real-time.
| |
MNS trigger (message queue)#
Consume messages from Message Service queues or topics.
| |
EventBridge trigger#
The most flexible option. We cover EventBridge in depth later in this article, but here is the trigger setup:

| |
Trigger comparison#
| Trigger | Latency | Use case | Max batch |
|---|---|---|---|
| HTTP | Sync, <100ms | API endpoints | 1 request |
| OSS | Async, 1-5s | File processing | 1 event |
| Timer | N/A | Scheduled tasks | N/A |
| SLS | 1-60s | Log analysis | Configurable |
| MNS | 1-5s | Message processing | 1 message |
| EventBridge | 1-5s | Complex event routing | 1 event |
Cold starts and performance#
Cold starts are the most discussed drawback of serverless. Understanding what causes them and how to mitigate them is essential for production use.

What causes a cold start#
A cold start happens when FC needs to create a new function instance. The sequence is:
- Download code (10-100ms for small packages, 1-5s for large ones)
- Start the runtime (50-500ms depending on language)
- Run initialization code (your module-level imports, connection setup)
- Execute the handler
Steps 1-3 are the cold start overhead. Step 4 is what you are billed for in a warm invocation. During a cold start, you are billed for all four steps.
Measuring cold starts#
Add timing to your function to measure the difference:
| |
Cold start benchmarks by runtime#
I measured cold starts for a minimal function (hello world + one import) across runtimes on FC in cn-beijing:
| Runtime | Cold start (p50) | Cold start (p99) | Warm invocation (p50) |
|---|---|---|---|
| Go 1.x | 60ms | 150ms | 1ms |
| Node.js 18 | 180ms | 400ms | 3ms |
| Python 3.10 | 250ms | 600ms | 5ms |
| C# .NET 6 | 400ms | 900ms | 8ms |
| Java 17 | 1,200ms | 3,000ms | 5ms |
| Custom Container | 2,000ms | 8,000ms | 5ms |
Java’s cold start is dominated by JVM startup. If you must use Java, GraalVM native image compilation can bring cold starts down to 200-400ms, but the build process is complex.
Mitigation strategies#

This is what concurrency looks like over a typical day. On-demand scaling tracks request rate but pays for it with cold starts on every spike; provisioned concurrency keeps a baseline of warm instances at the cost of idle time during the night. The three mitigation strategies below trade off these two failure modes.
1. Provisioned concurrency
Keep a set number of instances warm at all times. You pay for the idle time, but cold starts are eliminated.
| |
The cost: you pay for 5 instances continuously (about 0.000110592 CNY/GiB-second). For a 512 MiB function, that is roughly 0.055 CNY/s, or about 143 CNY/month for 5 instances. Worth it for latency-sensitive APIs; overkill for batch processing.
2. Scheduled pre-warming
If your traffic is predictable (e.g., spikes at 9:00 AM), use a timer trigger to invoke the function a few minutes before the spike:
| |
| |
3. Minimize package size
Every byte you add to your deployment package adds to cold start time. The code download phase is often the largest contributor.
| |
4. Optimize initialization code
Move expensive operations out of module scope when possible:
| |
5. Choose the right runtime
If cold start is your primary concern, the priority order is: Go > Node.js > Python > C# > Java. If development speed matters more than cold start, Python is the practical winner.
Layers and custom runtimes#
Layers: shared dependencies#

A layer is a zip archive containing libraries, a custom runtime, or other dependencies. Layers are versioned and can be shared across multiple functions. They solve two problems:
- Package size reduction. Move large dependencies (numpy, Pillow, etc.) into a layer. Your function code stays small = faster deploys and faster cold starts.
- Dependency sharing. Ten functions that all use Pillow can reference the same layer instead of bundling Pillow ten times.
Creating a layer#
| |
Using a layer in your function#
| |
Now your function code only contains your business logic, and the layer provides the heavy dependencies. Deploy time drops from minutes to seconds.
Custom runtimes#
When the managed runtimes are not enough — you need a specific system library, a compiled binary, or an ML model — use a Custom Runtime or Custom Container.
Custom Runtime (HTTP server mode)#
Your code runs as an HTTP server. FC starts your binary/script and sends requests to localhost:9000. You can use any language or framework.
| |
| |
When to use custom containers#
- ML inference: Bundle your model weights (up to 10 GiB via NAS mount) and inference framework.
- System dependencies: FFmpeg for video processing, ImageMagick for image manipulation, wkhtmltopdf for PDF generation.
- Non-supported languages: Rust, C++, or any language that compiles to a binary.
The trade-off is cold start time. Custom containers need to pull the image on cold start, which can take 2-10 seconds. Use provisioned concurrency for latency-sensitive workloads.
EventBridge#
EventBridge is the event routing layer. If Function Compute is the engine that runs your code, EventBridge is the switchboard that decides which code runs in response to which event. The AWS equivalent is Amazon EventBridge (formerly CloudWatch Events).
Core concepts#
| Concept | What it is | Example |
|---|---|---|
| Event bus | A channel that receives events. Default bus receives all Alibaba Cloud service events. Custom buses for your own events. | default, my-app-bus |
| Event source | Where events come from. Built-in sources (OSS, ECS, RDS) or custom (your application). | acs.oss, my.app |
| Event rule | A filter + target mapping. “When event matches this pattern, send it to that target.” | “OSS PutObject in uploads/ -> FC function” |
| Event target | Where matched events are delivered. FC, MNS, SLS, HTTP endpoint, another bus. | acs:fc:cn-beijing:123456:functions/process-image |
The event format#
Every event in EventBridge follows the CloudEvents 1.0 specification:
| |
This standardized format means your event processing code does not need to know the specifics of each Alibaba Cloud service’s event format — they all follow the same structure.
Built-in event sources#
EventBridge automatically receives events from these Alibaba Cloud services (partial list):
| Service | Event types | Example trigger |
|---|---|---|
| OSS | Object created, deleted, accessed | File upload processing |
| ECS | Instance state change, disk events | Auto-remediation on failure |
| RDS | Instance created, failover, high CPU | Database alerting |
| Container Service | Pod events, deployment changes | Deployment tracking |
| SLS | Alert triggered | Incident response |
| ActionTrail | API calls (audit log) | Security monitoring |
| Cloud Monitor | Alarm state change | Custom alerting pipeline |
| MNS | Message published | Message routing |
Creating event rules#
Event rules are the core of EventBridge. They filter events using JSON pattern matching and route matched events to targets.
| |
Event pattern matching#
The filter pattern supports several matching operators:
| |
This pattern matches: events from OSS where an object was created, the object is larger than 1 MiB, the key starts with uploads/ and ends with .jpg.
Available operators:
| Operator | Syntax | Matches |
|---|---|---|
| Exact match | ["value1", "value2"] | Field equals any listed value |
| Prefix | [{"prefix": "abc"}] | Field starts with “abc” |
| Suffix | [{"suffix": ".jpg"}] | Field ends with “.jpg” |
| Numeric | [{"numeric": [">", 100]}] | Field > 100 |
| IP address | [{"cidr": "10.0.0.0/8"}] | IP is in CIDR range |
| Exists | [{"exists": true}] | Field is present |
| Not | [{"anything-but": "error"}] | Field is not “error” |
Event transformation#
Before delivering events to a target, you can transform the event payload. This is useful when your target function expects a different format than the raw CloudEvent:
| |
Instead of receiving the full CloudEvent, your function receives:
| |
Custom events#
Your application can publish events to EventBridge for other services to consume:
| |
This lets you build fully event-driven architectures where different microservices communicate through EventBridge rather than direct API calls — loose coupling at its best.
EventBridge vs direct triggers#
You might wonder: why use EventBridge when FC already has direct OSS triggers?
| Feature | Direct FC trigger | EventBridge |
|---|---|---|
| Setup complexity | Simple | More configuration |
| Filtering | Basic (prefix/suffix) | Rich pattern matching |
| Fan-out | 1 function per trigger | Multiple targets per rule |
| Dead letter queue | No | Yes |
| Retry policy | Limited | Configurable |
| Cross-service routing | No (OSS-to-FC only) | Any source to any target |
| Event transformation | No | Yes |
| Audit trail | Limited | Full event history |
My recommendation: Use direct triggers for simple, single-function scenarios (e.g., “resize every uploaded image”). Use EventBridge when you need complex routing, multiple targets, or cross-service event flows.
API Gateway + Function Compute#
For building proper REST APIs, API Gateway sits in front of your functions and provides features that FC’s built-in HTTP trigger does not offer: authentication, rate limiting, request validation, and API versioning.

Creating an API backed by Function Compute#
| |
Custom domains#
Map your own domain to the API:
| |
Rate limiting and throttling#
| |
CORS configuration#
If your API is called from a browser, you need CORS headers. Handle this in your function:
| |
Solution: event-driven image processing pipeline#
Let’s bring everything together into a production-quality system. The architecture:
| |

Here is the full pipeline at a glance. One PutObject in the source bucket fans out into six derivative files in the target bucket — three sizes × two formats — and the entire flow runs in 2-3 seconds without a single server to manage.
Step 1: The function code#
| |
Step 2: Dependencies#
| |
Step 3: Serverless Devs configuration#
| |
Step 4: Terraform infrastructure#
| |
Step 5: Deploy and test#
| |
Expected output after uploading one image:
| |
Six output files from one upload. The whole pipeline runs in about 2-3 seconds and costs roughly 0.0001 CNY per image. Processing 10,000 images costs about 1 CNY.
Step 6: Add monitoring and error handling#

Async invocations get a managed retry queue for free. Configure the retry budget and an onFailure destination, and any event that exhausts retries lands in MNS for triage instead of being silently dropped.
For production, add a dead letter queue and alerting:
| |
Function Compute pricing#
FC pricing has three dimensions. Understanding them avoids bill shock.

FC bills along three independent axes: how often the function is invoked, how much memory × time it consumes, and how much data leaves the cloud. The free tier covers most hobby and small-business workloads outright.

| Dimension | Rate (cn-beijing) | Free tier (monthly) |
|---|---|---|
| Invocations | 0.0133 CNY per 10,000 invocations | 1,000,000 invocations |
| Execution duration | 0.000110592 CNY per GiB-second | 400,000 GiB-seconds |
| Public network outbound | 0.50 CNY per GiB | 1 GiB |
The free tier is generous. Let’s calculate a real workload:
Scenario: An API function with 512 MiB memory, 200ms average execution, called 5 million times per month.
| |
Sixteen CNY per month for five million API calls. An ECS instance to handle the same load would cost 30-50x more.
Provisioned concurrency adds cost. If you keep 5 instances warm with 512 MiB memory: 5 * 0.5 GiB * 86,400 s/day * 30 days * 0.000110592 = ~717 CNY/month. Provisioned concurrency is worth it only for latency-critical functions where cold starts are unacceptable.
For the Bailian API used with serverless functions for AI-powered processing, see our Bailian series .
FC vs AWS Lambda: a practical comparison#
If you are evaluating Function Compute against Lambda, here are the differences that matter in practice:
| Feature | Function Compute (FC) | AWS Lambda |
|---|---|---|
| Max timeout | 15 min (sync), 24h (async) | 15 min |
| Max memory | 32 GiB | 10 GiB |
| Max package size | 500 MiB (OSS) | 250 MiB (S3) |
| Temp storage | 10 GiB | 10 GiB |
| Provisioned concurrency | Yes | Yes |
| Container support | Yes (Custom Container) | Yes (Container Image) |
| VPC access | Yes (service-level config) | Yes (function-level config) |
| Layers | Yes (5 per function) | Yes (5 per function) |
| Free tier | 1M invocations + 400K GiB-s | 1M invocations + 400K GiB-s |
| GPU support | No | No (standard), Yes (Bedrock) |
| SnapStart (Java) | No | Yes |
| ARM support | No | Yes (Graviton2) |
| Pricing | ~15% cheaper in China regions | Standard global pricing |
The products are functionally similar. FC’s advantages are lower pricing in Chinese regions, higher memory ceiling (32 GiB vs 10 GiB), and the Service abstraction for grouping related functions. Lambda’s advantages are ARM support (lower cost per compute), SnapStart for Java, and a more mature ecosystem of extensions and integrations.
Summary#
Serverless is not always the answer. It excels at event-driven, bursty, short-lived workloads. It fails at long-running processes, GPU tasks, and ultra-low-latency requirements. Know the crossover point for your traffic pattern.
Start with Function Compute for new APIs. Unless you know you need persistent connections or sustained high throughput from day one, FC is cheaper, simpler, and operationally lighter. You can always migrate to ECS later — the reverse migration is harder.
Cold starts are manageable. Choose Go or Python for fast cold starts. Use layers to keep packages small. Use provisioned concurrency only for latency-critical paths. Pre-warm with timer triggers for predictable traffic patterns.
EventBridge decouples your architecture. Instead of point-to-point integrations (OSS trigger directly calls FC), route events through EventBridge. You get filtering, transformation, fan-out, dead letter queues, and an audit trail. The extra configuration pays for itself the first time you need to add a second consumer for the same event.
Use API Gateway for production APIs. FC’s built-in HTTP trigger is fine for internal services and prototypes. For anything public-facing, put API Gateway in front for authentication, rate limiting, and monitoring.
The image processing pipeline is a template. The pattern — OSS upload triggers EventBridge triggers Function Compute writes back to OSS — applies to any file processing workflow: PDF generation, video transcoding, data import, log parsing. Swap the processing logic and you have a new pipeline.
Next in this series, we tackle container orchestration with Container Service for Kubernetes (ACK) — for workloads that outgrow serverless but still need cloud-native operations. If you are looking for the infrastructure-as-code approach to deploying FC functions, the Terraform integration shown in this article’s solution section is the recommended starting point.
Alibaba Cloud Full Stack 12 parts
- 01 Alibaba Cloud Full Stack (1): The Ecosystem Map — What Alibaba Cloud Actually Is
- 02 Alibaba Cloud Full Stack (2): ECS — Compute That Actually Makes Sense
- 03 Alibaba Cloud Full Stack (3): VPC, SLB, and the Network Layer
- 04 Alibaba Cloud Full Stack (4): OSS — Object Storage Done Right
- 05 Alibaba Cloud Full Stack (5): RDS and PolarDB — The Database Layer
- 06 Alibaba Cloud Full Stack (6): RAM, KMS, and Cloud Security
- 07 Alibaba Cloud Full Stack (7): SLS, CloudMonitor, and Observability
- 08 Alibaba Cloud Full Stack (8): Serverless — Function Compute and EventBridge you are here
- 09 Alibaba Cloud Full Stack (9): OpenSearch and AI Search
- 10 Alibaba Cloud Full Stack (10): Bailian and DashScope — The LLM Layer
- 11 Alibaba Cloud Full Stack (11): PAI — The ML Platform
- 12 Alibaba Cloud Full Stack (12): End-to-End — One Terraform Apply for Everything