Technology reviews & practical guides
Explore serverless computing with AWS Lambda, Azure Functions, and Google Cloud Run. Learn when to go serverless and how to architect applications.

Serverless computing lets you run code without provisioning or managing any servers, paying only for the exact compute you consume. It has reshaped how teams build everything from APIs to data pipelines.
This article explains how serverless works, when it shines, and the trade-offs to weigh before adopting it.
With functions as a service such as AWS Lambda, Azure Functions, or Google Cloud Run, you upload small pieces of code that run in response to events: an HTTP request, a file upload, a message on a queue. The provider handles provisioning, scaling, and patching entirely behind the scenes.
Because functions scale to zero when idle, you pay nothing when there is no traffic, and they scale up automatically to handle sudden spikes.
When a function has not run recently, it may take a moment to initialize, adding latency to the first request. For latency-sensitive paths, plan for this with provisioned concurrency or alternative designs.
Serverless can also create vendor lock-in, complicate local testing, and become expensive for steady high-volume workloads where a dedicated server would be cheaper.
Serverless excels for event-driven tasks, APIs with variable traffic, scheduled jobs, and glue code between services. For constant heavy load or applications needing fine-grained control over the runtime, traditional servers or containers may serve you better.
A credible plan for a serverless architecture starts with event sources, concurrency, latency, state boundaries, observability, and total request economics. Write these constraints down before comparing products or copying reference architectures. The exercise exposes assumptions that otherwise appear only during an incident or migration.
Define success in operational terms: who owns the system, what failure looks like, how a change is approved, and how the team will recover. This keeps the design focused on durable outcomes rather than a fashionable tool list.

The safest implementation path is to implement one bounded event flow, make handlers idempotent, add tracing, and test retries and partial failures. Keep the first change deliberately small enough to inspect, reverse, and explain. Record the commands, policies, and decisions so the second implementation is repeatable rather than improvised.

The recurring failure patterns are unbounded concurrency, hidden downstream bottlenecks, large deployment packages, long synchronous chains, and missing dead-letter handling. These are governance and operating problems as much as technical ones, so another product rarely fixes them by itself.
Review access, dependencies, logs, capacity, recovery steps, and cost on a regular cadence. Test the uncomfortable path: remove a dependency, revoke a credential, restore from backup, or roll back a release. Rehearsal converts documentation into demonstrated capability.

A useful reference system is an event-driven order workflow using an API endpoint, short functions, a queue, idempotency records, and managed storage. The boundary matters because reliability and security failures usually occur between components rather than inside the most visible component. Draw the data flow, identities, network transitions, state stores, and external dependencies before selecting an implementation pattern.
For every boundary, document the input contract, owner, timeout, retry policy, capacity assumption, and failure response. Decide which component is authoritative for state and how duplicate, delayed, or malformed input is handled. These decisions prevent ambiguous recovery work when several systems report different outcomes.
Keep the first architecture intentionally legible. Fewer independently changing parts mean fewer credentials, dashboards, deployment paths, and failure combinations. Add a component only when it provides a measurable capability or isolates a meaningful risk; novelty by itself is not an architectural requirement.
Evaluate event contracts, timeout and retry behavior, concurrency limits, cold-start sensitivity, state ownership, observability, and downstream quotas. Weight each factor according to the workload rather than assigning every category equal importance. A regulated customer database, an internal reporting job, and a short-lived experiment can rationally produce different decisions even inside the same company.
Create a short scorecard, but attach evidence to every score: a measured latency, a tested recovery step, a policy excerpt, a representative invoice estimate, or feedback from the people who will operate the result. Unsupported numbers only turn preference into something that looks objective.
Set rejection criteria before the evaluation. A candidate that cannot meet a mandatory data boundary, recovery objective, accessibility need, or operational constraint should not win by accumulating points elsewhere. Record uncertainties separately and give them an owner and a deadline.
Consider this practical sequence: a request validates an order synchronously, queues fulfillment, and returns promptly while retries occur away from the customer-facing path. The team defines the expected result and failure signal first, then captures a baseline before changing production. It uses representative data and normal access controls rather than a frictionless demonstration account.
During the pilot, operators intentionally create one timeout, one authorization failure, and one malformed input. They verify that the event is visible, the user receives an appropriate result, retry behavior is bounded, and the documented recovery step actually works. This exercise often reveals more than a successful happy-path demo.
The final review includes application developers, operations, security, finance or procurement when relevant, and the business owner. Each group signs off on the risks it will own. The decision record states what was excluded from the pilot so limited evidence is not mistaken for universal proof.
Security work should include this concrete control set: least-privilege execution roles, signed events, secret rotation, dependency scanning, tenant isolation, and log redaction remain application responsibilities. Controls need owners and observable failure states. A setting that was enabled once but is never checked, tested, or reviewed is weaker than its configuration screen suggests.
The financial trade-off is equally contextual: per-request billing favors intermittent workloads, but sustained compute, verbose logs, provisioned concurrency, and data transfer can change the comparison. Estimate normal demand, peak demand, failure recovery, retained data, support, and operator time. A cheaper unit price can produce a more expensive system when it requires additional tooling or scarce expertise.
Do not optimize away the margin needed for recovery. Redundancy, logs, backups, test environments, and skilled review all cost money because they reduce uncertainty. Make those costs visible and compare them with the impact and likelihood of an interruption rather than labeling every unused percentage as waste.
For migration, place a stable API or queue boundary around each function, duplicate events during transition, compare results, and avoid migrating state and compute simultaneously. Establish data reconciliation and acceptance criteria in advance. A rollback is credible only when the team knows which writes occurred, which state must be reversed, and how users will be informed during the transition.
After launch, maintain a small operating calendar: review privileged access and dependencies, test restoration or rollback, inspect cost and capacity trends, update runbooks, and remove obsolete integrations. Link each recurring check to a named role instead of relying on collective memory.
Revisit the original decision when scale, regulations, staffing, product criticality, or vendor capability changes. Architecture is a managed position, not a permanent verdict. A concise decision log makes later changes faster because the next team can see which assumptions still hold.
When the system behaves unexpectedly, begin with scope and time. Identify which users, environments, regions, or transactions are affected and establish the first known bad event. Avoid making several speculative changes at once; every simultaneous change destroys evidence and makes recovery harder to reason about.
Collect function errors, throttles, duration percentiles, concurrency, queue age, duplicate events, dead-letter volume, and dependency latency. Preserve relevant evidence before restarting or redeploying components. Compare the failing path with one known-good path and check the most recent configuration, identity, dependency, or deployment change before assuming the underlying platform is broken.
Contain impact with the smallest reversible action. Pause a trigger, reduce a rollout, revoke one credential, isolate one resource, or route traffic back to a known version as appropriate. Communicate what is known, what is not yet known, who owns the next decision, and when the next update will arrive.
After recovery, build a timeline from durable evidence and distinguish the initiating event from the conditions that allowed it to spread. Assign follow-up work to owners with deadlines, add a test or signal that would catch recurrence earlier, and verify the corrective action instead of closing the review when a document is published.
Review runtime deprecations, function permissions, dependency versions, event contracts, concurrency assumptions, retained logs, and disaster replay procedures. High-risk access and active failure queues may justify weekly attention, while architecture assumptions and vendor fit may be quarterly topics. The cadence should follow the speed at which the underlying risk changes rather than an arbitrary reporting calendar.
Maintain a short service record containing purpose, owner, data classification, dependencies, support contacts, recovery objective, current version, cost center, and links to code and runbooks. This simple index shortens investigations and prevents critical knowledge from living only in one person's memory.
Track a balanced set of signals: an outcome for users, a reliability indicator, a security control, operating effort, and cost per useful unit. Review trends and meaningful exceptions rather than rewarding a single number. Metrics become dangerous when people optimize them while the original purpose is forgotten.
Finally, define retirement while the system is healthy. Know how to export required data, revoke identities, remove network paths, preserve audit evidence, stop billing, and inform dependents. Responsible lifecycle management includes a clean ending; otherwise temporary experiments become permanent, poorly understood attack surface.
Schedule a second review around platform change rather than only internal change. Cloud providers introduce new instance families, retire runtimes, revise quotas, and add regional capabilities continuously. Read deprecation notices, subscribe the operational owner to service-health communication, and test upgrades away from the production deadline. Confirm that capacity quotas can support both a demand spike and a recovery in another failure domain. Recalculate the cost model when traffic shape or data location changes, because an architecture that was economical at launch can shift as storage, logs, replicas, and transfer grow. Keep portable backups and documented dependencies even when migration is not planned; portability is most valuable before an urgent event.

There is no universal answer. Evaluate it against event sources, concurrency, latency, state boundaries, observability, and total request economics, then document why the chosen boundary fits the organization rather than copying another team's architecture.
Begin with the smallest useful scope. A narrow pilot makes implement one bounded event flow, make handlers idempotent, add tracing, and test retries and partial failures observable and reversible before the approach becomes a dependency for other teams.
Measure the outcome that matters to users and operators, not activity alone. Reliability, recovery effort, security exposure, and maintenance time usually reveal more than a raw feature count.
Assign a named owner, keep the configuration and decisions reviewable, and schedule periodic checks. A system without an owner quietly becomes operational debt.
More in Cloud Computing
Browse Cloud Computing