Swiss cheese coronavirus
Stack protection layers and see the infection risk that still gets through: a 70% mask, 50% better ventilation and an 80% vaccine leave a 3% residual, because 0.30 × 0.50 × 0.20 is 0.03, not 200% protection. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
The Swiss cheese coronavirus model treats every infection-control measure as a slice with holes: a mask, outdoor air, filtration, distance, vaccination, testing, and isolation each block some—but never all—of the pathways a respiratory virus uses to move from one person to another. When those slices are stacked, a virion has to pass through every remaining hole in sequence, so the residual transmission probability is the product of the individual leak fractions, not the sum of the effectiveness numbers people usually quote. This calculator accepts each layer's effectiveness as a percentage from 0 through 100, converts it to a leak of (100 minus effectiveness) divided by 100, multiplies the leaks, and returns the combined residual infection risk that still remains after the stack. A 70 percent mask, a 50 percent ventilation improvement, and an 80 percent vaccine layer do not add to 200 percent protection; they leave 0.30 × 0.50 × 0.20 = 0.03, a 3 percent residual. Use it to compare stacks, to show why a second imperfect layer still matters, and to fail loudly when any percentage sits outside 0–100 instead of inventing a risk figure.
How stacked layers multiply leaks into residual risk
The Swiss cheese respiratory-virus defence, popularised during the coronavirus pandemic as a public-health teaching diagram, starts from a blunt fact: no single intervention is a solid wall. A mask leaks at the edges, a filter only cleans the air that actually passes through it, a vaccine reduces infectiousness and susceptibility without making either zero, and physical distance still fails when people share a poorly ventilated room for a long time. Each layer is therefore a slice of Swiss cheese whose holes are the failure modes of that layer.
Transmission that still occurs after N independent layers is the event that a virion finds a hole in layer one and a hole in layer two and a hole in every remaining slice. Adding a 50 percent layer to an existing stack does not add fifty percentage points of protection; it multiplies the current residual by one half.
That is why a second imperfect control still matters even when the first already looks strong, and why quoting a sum of effectiveness percentages such as 70 plus 50 plus 80 equals 200 is not a probability at all.
Where a Swiss cheese coronavirus calculator earns its keep
Occupational-health and facilities teams use a Swiss cheese coronavirus calculator to compare candidate stacks before they spend budget: adding a portable HEPA unit at a stated 50 percent effectiveness to an existing mask-and-distance policy is a multiplication of the current residual, not a new headline percentage. School and campus planners can put published layer estimates side by side—source control, outdoor air, filtration, cohorting—and show a board why two 60 percent controls beat one 80 percent control under independence (0.16 residual versus 0.20).
Personal risk notebooks and journalism explainers need a deterministic oracle that refuses to print a number when someone types 110 percent effectiveness, instead of silently clipping and pretending the stack is stronger than the inputs allow. Failed validation does not consume balance. Keep the layer list short, pin the rounded residual in tests, and you get a reproducible stacked-risk figure without standing up an epidemiology simulator of your own.
What you can do with it
Workplace and school stack comparison
Compare mask, ventilation, and vaccination layers by residual transmission instead of adding headline effectiveness percentages that are not a probability.
Policy explainers and journalism widgets
Show why a second imperfect control still multiplies remaining risk, with a live Swiss cheese coronavirus calculator that rejects percentages outside 0–100.
FAQ
How is residual transmission computed from stacked layers?
Each layer's leak is (100 − effectiveness) / 100. Residual transmission R is the product of those leaks, assuming independent layers. Combined protection is 1 − R. Example: 70%, 50%, and 80% leave 0.30 × 0.50 × 0.20 = 0.03.
What happens if an effectiveness is outside 0–100?
Effectiveness must be a finite percentage in the closed interval 0–100; values such as −5 or 110 are rejected and not billed.
Does a 100 percent layer make residual risk zero?
Yes, under this independent-layer model a 100 percent effectiveness has leak 0, so the product R is 0 regardless of the other slices. That is a modelling assumption, not a claim that any real control is perfect.
Can I send unnamed percentages instead of named layers?
Objects with optional name are accepted for labelled slices.
Does adding a weak layer still help?
Yes. A layer that blocks 50% halves whatever risk is left, however strong the other layers already are. That is why a second imperfect measure still matters on top of a good first one.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/health/swiss-cheese-coronavirus \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"layers":[{"name":"mask","effectiveness":70},{"name":"ventilation","effectiveness":50},{"name":"vaccine","effectiveness":80}]}'const res = await fetch("https://api.kit.forhosting.com/health/swiss-cheese-coronavirus", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"layers": [
{
"name": "mask",
"effectiveness": 70
},
{
"name": "ventilation",
"effectiveness": 50
},
{
"name": "vaccine",
"effectiveness": 80
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/health/swiss-cheese-coronavirus",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"layers": [
{
"name": "mask",
"effectiveness": 70
},
{
"name": "ventilation",
"effectiveness": 50
},
{
"name": "vaccine",
"effectiveness": 80
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/health/swiss-cheese-coronavirus", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"layers":[{"name":"mask","effectiveness":70},{"name":"ventilation","effectiveness":50},{"name":"vaccine","effectiveness":80}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"layers":[{"name":"mask","effectiveness":70},{"name":"ventilation","effectiveness":50},{"name":"vaccine","effectiveness":80}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/health/swiss-cheese-coronavirus", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"layers": [
{
"name": "mask",
"effectiveness": 70
},
{
"name": "ventilation",
"effectiveness": 50
},
{
"name": "vaccine",
"effectiveness": 80
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "health.swiss_cheese_coronavirus",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_items | 40 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
How stacked layers multiply leaks into residual risk
If layer i blocks a fraction e_i of attempts—the effectiveness you type as a percentage—it leaks a fraction one minus e_i, and the residual transmission probability is the product of those leaks: R equals the product of (1 − e_i). This endpoint implements exactly that product and nothing more: it does not fit a dose-response curve, does not estimate community prevalence, and does not replace clinical or occupational-health advice. It turns a list of layer percentages into the residual risk that remains if those layers act independently of one another.
Input contract, response shape, and validation
Each item is either a finite number (the effectiveness percentage) or an object with required effectiveness and an optional name string such as mask, ventilation, or vaccine. Every effectiveness must be a finite number in the closed interval from 0 through 100 inclusive: zero means the layer does nothing (leak one), one hundred means the layer is modelled as a complete block (leak zero, residual zero for the whole stack). Optional names are omitted when you send bare numbers, never returned as null. POST a JSON body whose required field is layers: a non-empty array of at most forty protection slices. Aliases effectiveness, layer_effectiveness, and protections are accepted and parsed the same way, including a JSON array string or a comma-separated list of numbers. A value below 0 or above 100, a missing list, an empty list, a non-finite token, or more than forty rows fails with invalid_input naming the field, and those failures are not billed. On success the body includes layer_count; a layers trail with index, optional name, effectiveness, leak_fraction, and remaining_after after that slice; residual_transmission as a probability in 0–1 (the primary result); residual_percent on a 0–100 scale; combined_protection and combined_protection_percent as one minus the residual; and a formula string restating R = Π (1 − eᵢ/100). Example: mask 70, ventilation 50, vaccine 80 yields leaks 0.3, 0.5, and 0.2, remaining_after 0.3 then 0.15 then 0.03, residual_transmission 0.03, and combined_protection 0.97.
Integration use cases
Personal and notebook risk arithmetic
Turn a short list of layer effectiveness percents into residual_transmission for a notes app or script without importing a full epidemic model.
Technical questions
What does the Swiss cheese coronavirus calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.