Beginner's Guide to AWS Lambda: Serverless Functions Explained

Most cloud computing starts with a server you have to keep alive. AWS Lambda takes that away: you hand over a function, and it runs when something calls it. Nothing sits idle overnight, no operating system needs patching at the weekend, and your bill usually tracks the work that was actually done rather than the machines you reserved.

"Serverless" is a slightly misleading name. There is plenty of server involved — you just never log into it. What you give up in control, you gain in time. What follows is how Lambda really works, why the first request to a fresh function can feel sluggish, how the pricing maths runs, and where a container is still the better answer.

What actually happens when a function runs

Every Lambda deployment contains three things: your code, a runtime (Node.js, Python, Java, Go, .NET, Ruby, or a custom one), and a handler — the specific function AWS calls when an event arrives. You also attach an IAM role, which decides what your code is allowed to touch. That role is where a lot of first projects go wrong. A function that cannot read from S3 usually has a permissions problem, not a coding problem.

When an invocation arrives, AWS checks whether an execution environment for your function is already sitting warm. If one is, your handler runs almost immediately. If not, the platform creates one: a lightweight micro-virtual machine, the runtime, and any code you run outside the handler. That gap is the cold start.

Environments are reused, so variables and objects created outside the handler survive between invocations. That is why database clients and SDK objects belong at module level rather than inside the handler. Do not treat them as permanent, though; AWS can recycle an environment at any time, so anything that must persist belongs in a database or object store.

Three ways a function gets triggered

  • Synchronous — API Gateway, a load balancer, or a direct SDK call waits for the response. Latency is visible to the user, so cold starts matter here.
  • Asynchronous — S3 events, SNS, EventBridge. AWS queues the event and retries on failure, so a few hundred milliseconds of startup is irrelevant.
  • Poll-based — SQS or Kinesis. Lambda polls the source and invokes your function in batches, with failures handled through the queue's own retry and dead-letter settings.

Cold starts, without the panic

A cold start is the price of not paying for idle servers. In practice it is often tens of milliseconds, occasionally a second or more. The things that push it upwards are predictable: a large deployment package, a heavy runtime such as Java or .NET with a big framework, initialisation code that opens connections or loads models, and — less of an issue than it once was — attaching a function to a VPC.

If latency is critical, start with the cheap fixes. Trim the package, keep dependencies lean, and move slow initialisation outside the handler only when that object is genuinely needed on every call. Consider the Arm-based Graviton runtime too, which tends to cost less and often runs slightly faster. Beyond that, provisioned concurrency keeps a set number of environments ready, but you pay for them whether they are used or not. SnapStart, available for Java, takes a different route by snapshotting an initialised environment.

How the pricing actually works

The bill has two parts: a charge per request, and a charge for compute time measured in gigabyte-seconds — memory multiplied by how long the function ran. Time is measured in small increments, so a function finishing in 40 milliseconds is not rounded up to a full second. A monthly free tier covers a reasonable amount of both for small projects; check the current allowances before you plan around them.

Memory is the dial that catches people out. Choosing 1,024 MB instead of 256 MB costs roughly four times as much per second, but it also gives your function around four times the CPU. Sometimes the faster run is the cheaper one. Test a few memory settings against a realistic workload and compare total cost, not the per-second rate.

Watch the surrounding services as well. A function inside a VPC that talks to the public internet routes through a NAT gateway, and that data processing charge can dwarf the Lambda bill. API Gateway, CloudWatch Logs and data transfer all add up too.

Serverless or containers?

Lambda and containers solve overlapping problems, and plenty of systems use both. The deciding factors are usually runtime, traffic pattern, and how much operational control you need.

Choose Lambda when:

  • traffic is spiky, unpredictable or mostly idle, so paying per request beats paying per hour
  • the work is event-driven and short — resizing an image, handling a webhook, moving a record between systems
  • tasks finish in minutes rather than hours (the maximum runtime is 15 minutes)
  • you would rather not think about patching, scaling or capacity planning

Choose containers on ECS, EKS or Fargate when:

  • utilisation is high and steady, so a long-running task is cheaper per unit of work
  • you need a custom operating system, native binaries, a GPU, or a runtime Lambda does not support
  • processes run for hours or hold connections open for long periods
  • you want one deployment artefact that behaves identically on a laptop and in production

Habits that keep things quick and cheap

  1. Keep the handler thin: parse the event, call a service or two, return a clear result.
  2. Log in structured JSON so you can query CloudWatch Logs instead of reading it line by line.
  3. Set a sensible timeout. The default is often too tight for network calls, while a 15-minute limit hides runaway loops.
  4. Add provisioned concurrency only where you have measured a real problem.
  5. Give each function one job. A "does everything" function is hard to secure and harder to debug.
  6. Store state externally. Between invocations, /tmp may still be there, but you should never depend on it.
If you can describe a piece of work as "when this happens, do that", Lambda is probably a good fit.

A practical way to start

Pick something small and real: a webhook receiver, a scheduled job that emails a report, or a function that creates a thumbnail when an image lands in S3. Deploy it with a framework such as AWS SAM or the CDK so your infrastructure lives in version control, test it locally before pushing, and add an alarm on errors. Once one function runs smoothly, the rest of the model falls into place quickly.

If you are weighing Lambda against containers, price your actual traffic rather than a theoretical worst case. Most teams land on a mix — Lambda for events and glue, containers for steady heavy lifting — and that is usually the least dramatic, most durable answer.

Photo: cookieone / Pixabay

Related News
New Year Codebase Health Check: A January Checklist for Development Teams

A practical January checklist for development teams: audit dependencies, target test coverage, prune...

Why Your CSS Grid Layout Breaks on Mobile: Common Mistakes and Fixes

CSS Grid usually breaks on mobile because of sizing floors, not the grid itself. Here's why implicit...

A Developer's Checklist for GDPR-Compliant Logging

A practical checklist for keeping personal data out of application logs, setting sensible retention...