Skip to main content

Runtime and Deployment Foundations

The question for this group

What changes between running an app on my laptop and running it for users?

Build the vocabulary before opening the AWS console.

Topics to explore​

  • DevOps ownership: development, operations, environments, and the software delivery lifecycle.
  • Linux and the shell: files, permissions, pipes, exit codes, and useful diagnostic commands.
  • Processes and services: ports, signals, background work, CPU, memory, and disk.
  • Build artifacts and dependencies: lockfiles, reproducible builds, static output, and server runtimes.
  • Configuration: environment variables, build-time versus runtime values, and secrets versus public configuration.
  • Request fundamentals: DNS, TCP, TLS, HTTP, proxies, browser errors, and server errors.

Notes​

DevOps ownership​

Traditionally, developers wrote code and handed it off to an operations team to deploy and maintain. DevOps ownership collapses this wall.

"You build it, you run it."

It means taking responsibility for how your application behaves in reality—understanding its deployment pipeline (CI/CD), its host environment, and its lifecycle in production. If it works on your laptop but crashes in staging, it's still your problem.

Linux and the shell​

The mental model: Everything is a file, and streams connect them.

When moving from a local laptop to a server, the interface changes from a GUI to text. Understanding this environment relies on a few core concepts:

Everything is a file: Text documents, directories, network connections, and hardware devices are all treated as files by the OS.

Permissions (rwx): Because servers run processes under restricted users (e.g., node instead of root), permission errors are the most common deployment gotcha. A file has Read, Write, and Execute limits.

Streams & Pipes (|): Programs have invisible data streams: stdin (input), stdout (normal output), and stderr (error output). The pipe operator (|) connects the stdout of one program directly to the stdin of another, allowing you to chain commands.

Exit codes: When a program finishes, it leaves behind a hidden number (0-255). 0 means success. Any number > 0 means failure. This is how CI/CD pipelines know if a build or test suite passed—they don't read logs; they read the exit code.

The Diagnostic Vocabulary​

When an app fails in production, you don't write code—you observe.

Tailing logs

Watching a log file update in real-time.

Why: To see errors exactly as they happen.

Grepping

Searching massive text streams for a pattern.

Why: Finding specific stack traces or "ERROR" lines.

Checking processes

Listing currently running programs.

Why: To see if your app actually started or crashed.

Checking ports

Verifying what network ports are active.

Why: To confirm your app successfully claimed port 8080.

Processes and services​

The mental model: An app on disk is dead code. When you run it, it becomes a "process"—a living organism in RAM that claims resources, listens for messages, and eventually dies.

Ports​

A process needs a "door" for the outside world to talk to it. A port is just a numbered door (e.g., port 3000). Only one process can listen on a door at a time. If your app crashes but leaves the port open, the next time you start the app it will fail with EADDRINUSE.

Terminal
# Find out exactly which process is hogging port 3000
lsof -i :3000

Background work (Daemons)​

When you close your terminal, any process attached to it dies immediately. To keep a server running forever, it must be detached and run as a "daemon" or background service.

Terminal
# Start a process in the background, ignoring terminal hangups (nohup)
nohup node server.js &

Signals​

The OS doesn't ask processes nicely to stop; it sends signals.

  • SIGTERM (Signal 15): "Please shut down." The app can clean up database connections before dying gracefully.
  • SIGKILL (Signal 9): "Die instantly." The OS forcefully assassinates the process.
Terminal
# Send a graceful SIGTERM to a specific Process ID (PID)
kill 1234

# Send a forceful SIGKILL (if the app is frozen and won't respond)
kill -9 1234

Resources (CPU, Memory, Disk)​

Processes eat resources. If a memory leak causes a process to eat too much RAM, the OS has a panic mechanism called the OOM (Out Of Memory) Killer, which will violently kill your process to save the server.

Terminal
# View live CPU and memory usage of all processes (like Task Manager)
top

Build artifacts and dependencies​

The mental model: Your source code isn't what runs in production. What runs is a "build artifact"—an immutable, packaged snapshot of your code and all its exact dependencies frozen in time.

When you develop on your laptop, your environment changes constantly. In production, deployments need to be perfectly predictable.

The Lockfile

package-lock.json or yarn.lock.

Why: It guarantees the server downloads the exact same dependency versions you tested locally.

Reproducible Builds

Building the exact same code twice yields the exact same output.

Why: Essential for safe rollbacks. If a deploy breaks, you revert to the previous known-good artifact.

Static vs Runtime

React builds to static HTML/JS. Node.js requires a runtime.

Why: Static files go on cheap, global CDNs. Runtimes require dedicated servers or containers.

The Golden Rule of CI/CD Dependencies​

When a build server prepares your application for deployment, it must strictly respect the lockfile to ensure reproducible builds.

Terminal
# NEVER use regular 'npm install' in a deployment pipeline!
# It might secretly update sub-dependencies and break the build.
npm install ❌

# ALWAYS use 'npm ci' (Clean Install).
# It strictly follows the lockfile and throws an error if things are out of sync.
npm ci ✅

Back to the full roadmap.