The conclusion first
If an application already has an ECS instance running continuously and a small job executes only a few times per day, keeping the job on that instance is often reasonable. The server is already paid for, so the marginal cost of one more script may be close to zero. Moving it to Function Compute or AWS Lambda merely to appear cloud-native can add deployment, permission, observability and invocation costs.
The real value of Function as a Service is not that it can also run cron. It is that it can:
- Execute directly when an event occurs instead of continuously polling.
- Create more execution environments when work suddenly increases.
- Give each workload an independent permission, resource and failure boundary.
- Run code without the team operating another server.
I reduce the decision to one question:
Is this something the server routinely does, or something independently triggered by an event?
The first often belongs on ECS. The second is where Function Compute or Lambda becomes interesting.
There is more than one kind of cost
For a small system, cost often matters more than theoretical scalability. The comparison should include more than the cloud invoice:
Total cost = compute + operations + failure handling + reserved capacity + system complexity
| Choice | What it saves | What it adds |
|---|---|---|
| ECS cron or worker | Reuses paid capacity and one deployment system | Host maintenance, scheduling reliability and resource contention |
| Function Compute or Lambda | Avoids an idle worker and provides event integration and scaling | Invocation cost, cold starts, cloud integration and additional observability |
FaaS is generally billed by requests and execution resources, which can be attractive for infrequent or bursty work. For a workload that consumes resources steadily for long periods, an ECS instance or container worker may be more predictable. Alibaba Cloud itself describes Function Compute as event-driven, on-demand compute—not the default destination for every workload. Function Compute overview
When I keep the job on ECS
I prefer ECS when:
- The instance already runs all day and has spare capacity.
- Frequency and resource consumption are stable.
- The job shares code, data and a release cycle with the main application.
- It runs for a long time or needs local files, special binaries or long-lived connections.
- The team already has job records, locking, retries, logs and alerts.
A small internal report generated once per day from the same application database is a good example. Extracting it into a function may not create enough value to justify another deployment surface.
A host-based schedule still needs answers: can a deployment skip the run, will multiple instances run it twice, can two runs overlap, and can the job starve the online API? Small systems can address these with a lock, execution records and monitoring. They do not automatically need a larger platform.
When I use Function Compute or Lambda
Signals that favor FaaS include:
- An OSS or S3 object, queue message or webhook should trigger immediate work.
- Traffic is usually absent but occasionally bursts.
- Jobs are stateless, independent and highly parallelizable.
- The workload needs a separate resource or permission boundary from the API.
- The team does not want to operate another worker fleet.
- Failures fit retry, destination or dead-letter queue semantics.
Consider thumbnail generation after an upload:
flowchart LR
U[User upload] --> O[OSS / S3]
O --> E[Object-created event]
E --> F[Function]
F --> R[Thumbnail / metadata]
This is more direct than making ECS scan a bucket every few minutes. Function Compute supports time, OSS, messaging and EventBridge triggers. Lambda similarly supports sources such as S3, SQS and EventBridge Scheduler through push or pull integration. Alibaba trigger overview, AWS event-driven architectures
Isolation has value, but it must justify its cost
Moving a job out is also a decision about failure boundaries.
If a batch unexpectedly exhausts CPU, memory or database connections, sharing an ECS instance with the online API is risky. A separate function can have its own resources, permissions, deployment and concurrency limit. The team also gains another runtime, log stream, IAM policy and cost item to understand.
My rule is not “split whenever possible.” It is:
Split when the risk reduced by isolation is worth more than the system and cloud cost it introduces.
Low traffic does not mean the job must stay forever. Start on ECS, record executions, prevent duplicates, constrain its resources and define migration triggers: it begins affecting API latency, queue delay crosses a threshold, immediate cloud-event integration becomes necessary, or its operating burden exceeds the price of a managed function.
FaaS is not the same as microservices
Microservices describe business and team boundaries. Function Compute and Lambda describe deployment and execution models.
- A microservice can run on ECS, Kubernetes or FaaS.
- A function can be one event handler belonging to a larger service.
- Deploying every small function separately can create untraceable nano-services rather than good microservices.
Choose business boundaries first, then select the execution model for each workload. Do not choose serverless first and derive the system boundaries afterward.
A practical decision table
| Situation | Prefer |
|---|---|
| Existing ECS, small infrequent schedule | ECS cron or systemd timer |
| Stable continuous computation | ECS or container worker |
| File, message or cloud-resource event | Function Compute or Lambda |
| Infrequent, bursty and parallel work | Function Compute or Lambda |
| Very low latency with steady traffic | Resident service |
| Long, multi-step process with compensation | Workflow, queue or batch platform |
| Future scale is still unknown | Start simple and define a migration threshold |
FaaS is not infinitely elastic. Concurrency, timeout, payload and downstream capacity limits still apply, and cold starts may add latency. Pre-warming or provisioned concurrency can reduce that latency, but it reintroduces a form of standing cost. Function Compute cold-start guidance, AWS Lambda execution environments
The final decision
Architecture does not become more mature by using more services. While requirements and traffic are small, running a scheduled job on an existing ECS instance—with locking, execution records and monitoring—may be the most cost-aware answer. Move that workload to Function Compute or Lambda when event integration, isolation or burst scaling becomes a real constraint.
This is the same discipline as requirement analysis: pay for what is necessary today, preserve a seam where change is likely, and upgrade when evidence arrives. Good design does not prepay for every possible future. It keeps the system movable when that future becomes real.