Operations Research · A Primer

The science of better decisions

Built for Sahil — what OR actually is, where it shows up in everyday life, and how it maps directly onto your containershipd project.

Field: Operations Research / Industrial Engineering At GT: the Stewart School of ISyE Your hook: containershipd = a live OR playground

Making the best decision, not just a working one

Operations Research (OR) is the discipline of using math and models to make better decisions when resources are limited and choices interact. If programming asks "how do I make this run?", OR asks "of all the ways this could run, which one is best — and can I prove it?"

1940s
Born in WWII
$B+
Saved yearly by airlines, logistics, energy
#1
GT ISyE — top OR program in the US
3
Ingredients: objective, variables, constraints

Where it came from

In World War II, Britain put mathematicians and physicists onto military "operations": where to place radar, how big to make convoys, how to hunt submarines. They found that analyzing the operation beat gut instinct — larger convoys lost proportionally fewer ships, for example. After the war those same techniques moved into industry: factories, airlines, supply chains, hospitals. Today it powers ride-share dispatch, delivery routing, power-grid scheduling, and cloud resource allocation — including systems like yours.

Every OR problem is the same three-part sentence: choose these things, to make this as good as possible, without breaking those rules.

— the entire field in one line

The three ingredients of any model

Decide

Decision variables

The knobs you control — what you're actually choosing.

containershipd: which host each deployment lands on; how much CPU to grant.
Optimize

Objective

The single number you want to push as high (or low) as possible.

containershipd: maximize apps served per server — or minimize wasted RAM.
Respect

Constraints

The hard limits the answer must obey.

containershipd: a host's total CPU/memory; each user's quota.

How an OR project actually flows

The Modeling Loop
01
Frame
Name the decision, goal & limits
02
Model
Write it as math (variables + constraints)
03
Solve
Run a solver / algorithm
04
Validate
Does it beat the status quo?
OR is iterative — you refine the model as reality pushes back. The loop closes when the answer is trusted enough to ship.

Why this matters for you specifically

Georgia Tech's H. Milton Stewart School of Industrial & Systems Engineering (ISyE) is the #1-ranked program of its kind. OR/IE is one of your approved majors — and containershipd is already an OR system in disguise. Every scheduler, quota check, and load balancer you've written is an optimization problem waiting to be named.

Seven tools that cover most of the field

You don't need all of OR to be dangerous. These are the workhorses — each answers a recognizable shape of question. Learn to spot the shape and you'll know which tool to reach for.

Continuous

Linear Programming (LP)

Split a fixed pool of resources to maximize/minimize a goal, when everything scales linearly.

Shape: "how much of each, given limited supply?"
Whole numbers

Integer & Combinatorial Optimization

Same idea, but choices are yes/no or whole units — pick, assign, sequence. Much harder, hence clever algorithms.

Shape: "which items / which assignment?"
Waiting lines

Queueing Theory

Predict waiting time and utilization when jobs arrive randomly at limited servers.

Shape: "how long is the wait? how many servers?"
Graphs

Network Flows & Shortest Paths

Route things through a graph of nodes and edges — cheapest path, max throughput, best matching.

Shape: "how do I get from A to B through a network?"
Time & order

Scheduling

Decide what runs when, on which machine, so deadlines are met and idle time is low.

Shape: "in what order, on what resource, by when?"
Uncertainty

Simulation & Stochastic Models

When the math is too messy, imitate the system with random inputs and measure what happens.

Shape: "what if demand is random? test it 10,000 times."
Stages

Dynamic Programming

Break a big sequential decision into overlapping sub-decisions and reuse the answers.

Shape: "decide step by step, remembering the best so far."
The meta-skill

Modeling itself

The rarest skill isn't solving — solvers do that. It's translating a messy real system into the three ingredients cleanly. That's the craft ISyE teaches.

Solvers do the heavy lifting

You rarely code the optimization algorithm yourself. You describe the model in a library — OR-Tools, PuLP, Gurobi — and a decades-tuned solver returns a provably optimal (or near-optimal) answer in milliseconds. Your job is the model, not the math grind.

You already use OR every day

These aren't textbook abstractions — they're systems you touch constantly. Each one is a named OR problem under the hood.

Google Maps — the shortest path problem

The road network is a graph: intersections are nodes, roads are edges weighted by travel time. "Fastest route" is literally the classic shortest-path problem, solved by Dijkstra's algorithm (and faster variants) millions of times a second.

The coffee shop line — queueing theory

A single-server queue (M/M/1)
arrivals λ = 40/hr waiting line barista μ = 50/hr served & gone
Serve slightly faster than people arrive (μ > λ) and the line stays short. Let arrivals creep toward capacity and wait time explodes — non-linearly. That "explosion near 100% utilization" is why you never run a server at 99% load.

The diet problem — linear programming's origin story

One of the first LPs (1940s): pick quantities of foods to hit all nutrient minimums at the lowest cost. Foods = decision variables, price = objective, "≥ 2000 calories, ≥ 50g protein" = constraints. The feasible answers form a polygon; the optimum always sits at a corner.

Why LP optima live at corners
food A → food B → feasible region lower cost → optimum
Slide the objective line as far as the constraints allow — it always stops touching at a corner. That single fact is what makes LP fast to solve, even with thousands of variables.
Logistics

Delivery routing (UPS ORION)

Choosing the order to visit stops — the Traveling Salesman / Vehicle Routing problem. UPS reports ~100M miles saved per year.

Aviation

Crew & fleet scheduling

Assigning planes and crews to flights under legal rest rules — massive integer programs solved nightly.

Manufacturing

Cutting stock

Cut raw sheets/rolls into ordered sizes with the least waste — the same math as packing containers onto a host.

Sports

League scheduling

Building a season fixture list that satisfies venue, travel, and TV constraints — a constraint-satisfaction problem.

containershipd is an OR engine

Your daemon manages Docker Compose deployments: it enforces per-user quotas (CPU cores, memory, storage, bandwidth), injects resource limits, polls metrics every 30s, redeploys on webhooks, and routes traffic through Traefik. Almost every one of those is a textbook OR problem.

The deploy flow, seen as a decision pipeline

From git push to running container
Trigger
Webhook
GitHub push arrives — maybe many at once
Queue
Redeploy job
Builds compete for CPU & I/O
Decide
Placement + limits
Fit into quota & host capacity
Serve
Traefik route
subdomain → service:port
Each stage hides an optimization question: how many builds to run at once? which host? how much CPU to grant? how to balance routed traffic?

The core problem: packing deployments onto hosts

Each deployment declares a CPU limit and memory limit. A host has finite cores and RAM. Deciding which deployments fit on which host — using the fewest hosts, or fitting the most valuable set on the host you have — is the bin-packing / knapsack problem. Here's the difference between a naive first-fit and a packed result:

Same 4 deployments · 2 GB hosts
HOST 1 · naive
web · 512MB
api · 384MB
~1.1 GB idle
HOST 2 · naive
db · 768MB
cron·256
~1.0 GB idle
HOST 1 · packed
db · 768MB
web · 512MB
api · 384MB
cron·256
~0.13 GB
1920 MB fits on one 2 GB host — so the packed plan needs one server, not two.
First-fit spreads apps thin and strands capacity across two half-empty hosts. A packing solver squeezes the same four apps onto one, freeing HOST 2 entirely. This is exactly cutting-stock and cloud bin-packing.

The full mapping

containershipd featureOR problemMethod / toolPayoff
Placing deployments on hosts within CPU/RAM limitsVector bin packingILP / first-fit-decreasingFewer servers
Admitting the best set of apps onto one host under quotaMulti-dimensional knapsackILP / greedy ratioMax value/host
How many concurrent builds/redeploys to runQueue with c serversM/M/c, Little's LawBounded wait
Bursts of webhook redeploys after a big pushArrival surge / schedulingPriority schedulingNo thundering herd
Safe CPU/memory overcommit ratioResource allocation under riskLP + stochastic/chance constraintsDensity w/o OOM
Traefik routing subdomain → service:portLoad balancing / assignmentMin-cost flow / round-robinEven load
Metrics polled every 30s, 24h retentionSampling & forecastingTime-series / EWMAPredict, pre-scale
Setting default quota tiers (3 deploys, 2 cores…)Design under a budgetSimulation / LPFair & profitable

The one to build first

Your quota system already tracks each user's maxCpuCores and maxMemoryMb. Turning the "does this deployment fit?" check into a real packing decision — choosing the host that leaves the least wasted capacity — is a self-contained, demoable OR feature. See the next tab for a concrete model.

A packing model you could actually ship

Let's turn one containershipd decision into a real optimization model, end to end: given a host and a set of pending deployments, admit the most valuable set that fits. This is the multi-dimensional (0/1) knapsack.

Step 1 — Name the three ingredients

  1. Decision variables: for each pending deployment i, a yes/no variable x_i ∈ {0,1} — admit it to this host or not.
  2. Objective: maximize total value Σ value_i · x_i (value could be plan tier, priority, or just "count of apps served").
  3. Constraints: admitted apps can't exceed the host's cores or its memory — two constraints, hence "multi-dimensional".

Step 2 — Write it as math

# Multi-dimensional 0/1 knapsack for one host maximize Σi valuei · xi subject to Σi cpui · xi ≤ HOST_CORES # CPU fits Σi memi · xi ≤ HOST_MEMORY_MB # RAM fits xi ∈ {0, 1} # admit or don't

Step 3 — A tiny instance

Host has 2.0 cores and 2048 MB. Five deployments are waiting. Which set maximizes value?

DeploymentCPUMemoryValueAdmit?
web0.5512 MB3✓ in
api0.5384 MB3✓ in
db0.8768 MB4✓ in
analytics1.61600 MB7✗ out — the tempting trap
cron0.2256 MB1✓ in
Chosen set2.0 / 2.01920 / 2048value 11optimal

A greedy "highest value first" heuristic grabs analytics immediately — it's the single most valuable app (value 7) — but it hogs 1.6 cores and 1600 MB, leaving room for only cron. Greedy total: 8. The optimal solver resists the trap, leaves analytics out, and admits the four smaller apps for a total value of 11. That gap — 11 vs 8 — is exactly why OR beats gut instinct.

Step 4 — The solver call (OR-Tools, Python)

from ortools.linear_solver import pywraplp solver = pywraplp.Solver.CreateSolver("CBC") x = {i: solver.BoolVar(f"x_{i}") for i in deployments} # two capacity constraints — the "multi-dimensional" part solver.Add(sum(cpu[i] * x[i] for i in deployments) <= HOST_CORES) solver.Add(sum(mem[i] * x[i] for i in deployments) <= HOST_MEMORY_MB) solver.Maximize(sum(value[i] * x[i] for i in deployments)) solver.Solve() admitted = [i for i in deployments if x[i].solution_value() > 0.5]

Scaling up = the real project

One host is a knapsack. Many hosts is bin packing — add a y_h "is host h used?" variable and a "each deployment goes to exactly one host" constraint, then minimize hosts used. That single extension turns a demo into a genuine cluster scheduler, and it's a great thing to write about in an application essay.

Where to take this next

You have the rare combination the field wants: you can build the system and you can model the decision. Here's how to deepen both.

Learn

Concepts to chase

  • Linear & integer programming (start with the diet + knapsack problems)
  • Queueing basics — Little's Law: L = λ · W
  • Graph algorithms: shortest path, max-flow / min-cut
  • Greedy vs optimal, and when a heuristic is "good enough"
Build

Tools to try

  • OR-Tools (Google) — free, batteries-included, great docs
  • PuLP — simplest Python LP/ILP modeling
  • Gurobi / HiGHS — industrial-grade solvers (free academic license)
  • SimPy — discrete-event simulation for queue experiments

Three project moves for containershipd

Move 1

Smart placement

Replace first-fit host selection with the knapsack model from the last tab. Measure hosts saved.

Move 2

Build queue sizing

Model concurrent builds as an M/M/c queue; pick c so p95 wait stays under a target.

Move 3

Overcommit dial

Use 24h metrics to safely oversell CPU — a chance-constrained allocation problem.

The GT ISyE angle

If OR/IE is on your list, containershipd is the perfect artifact: a working system where you can point at a real scheduling decision and say "I modeled this as a bin-packing ILP and cut host count by X%." That's exactly the systems-thinking ISyE looks for — engineering plus optimization, not just code.

Operations Research is just refusing to accept "it works" when "it's the best possible" is provable.

— the mindset to carry forward

Five questions. Fresh every run.

Each run pulls 5 questions from the bank, rephrases them, and reshuffles the answer options and distractors — so you're recalling the concept, not memorizing a position or wording. Hit Score when you're done, or New run for a different set.

Bank: 11 concepts · 5 shown per run · options & phrasings randomized client-side · no network calls.