---
title: 'Private Connectivity and Peering'
source: 'https://academia.sh/en/courses/compute-and-networking-in-the-cloud/private-connectivity-and-peering'
course: 'Compute and Networking in the Cloud'
language: en
updated: '2026-09-13T05:07:38+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Compares the public endpoint, peering, and private link on the same workload: reachable items, latency, period fictional units, and rule count'
    - 'Counts with real address arithmetic how many network pairs address space overlap leaves unpeerable, and works out the cost of re-addressing'
    - "Measures the effect of peering's non-transitivity on the number of peerings and routing lines, and compares it against a central transit layer"
    - 'Counts item by item the decisions private link hands off to the provider, and shows the surface that narrows in exchange'
---

# Private Connectivity and Peering

The three ways two networks connect to each other are counted on the same workload: peering raises reachable items from one to 384 and hands off no decision, private link keeps items at one but gives four of six items to the provider; in a seven-network address plan, four of twenty-one pairs cannot be peered because of overlap, and the fix is re-addressing three networks; because peering is not transitive, the sixty-six peerings twelve networks need call for 660 routing lines.

The previous lesson moved content to the edge and completed the path of the request coming from
outside. This whole path faces a single direction: toward a client arriving from the **public
network**.

The fictional regional measurement network's own components also send requests to each other. The
collector network writes to the data warehouse, the dashboard calls a shared validation service
sitting in another account. None of this traffic is client traffic — but today it flows through
the same path as client traffic: with public addresses, over the public network, using the full
surface of the gateway and the edge.

Two networks can connect to each other without ever going out to the public network. **Peering**
connects two networks directly, **private link** opens only a single service through a single
endpoint. This lesson compares all three on the same workload and asks the course's question one
last time.

- **CN49.** The fictional measurement network's components sit in separate networks; the period's
  flow volume is 2,400. The counterpart network has 96 instances, and each instance listens on
  four ports. Our own side has five route tables.
- **CN50.** The latency values are fictional model constants: 14 ms for the public endpoint, two
  for peering, three for private link. The model does not measure time, it writes the constants.
- **CN51.** The prices are fictional, the currency's name is **unit**: public egress is two units
  per hundred volume, the inter-network private path is one unit, the private link endpoint's
  period rent is 25 units. The central transit layer is a fixed 120 units a period plus 30 units
  per connection.
- **CN52.** Seven networks' address blocks are fictional and all in private ranges; the address
  arithmetic is real. The 1,604-unit cost of re-addressing comes in as an **input** from this
  topic's first lesson.
- **CN53.** Peering is not transitive: a peering only reaches its own two ends. The network to
  re-address is chosen **greedily** — the most-overlapping network moves first.

```js
// connectivity/inter-network.mjs — model: the ways two networks connect to each other. Fictional
// regional measurement network; no real network is set up, the address arithmetic is real. The unit's name is "unit".
const PEER_INSTANCES = 96, PORTS = 4, TABLES = 5, VOLUME = 2400;
// [path, reachable items, latency(ms), unit per 100 volume, period-fixed,
//  routing lines, filter rule, external record]
const PATH = [
  ["public endpoint", 1, 14, 2.0, 0, 0, 2, 1],
  ["peering", PEER_INSTANCES * PORTS, 2, 1.0, 0, TABLES, 2, 0],
  ["private link", 1, 3, 1.0, 25, 0, 1, 0],
];
// [decision item, public endpoint, peering, private link]
const DECISION = [
  ["which range the route is written to", "you", "you", "provider"],
  ["which service on the other side is reachable", "other side", "you", "provider"],
  ["which direction traffic can originate from", "you", "you", "provider"],
  ["the exit address being registered on the other side", "you", "n/a", "n/a"],
  ["name resolution", "you", "you", "provider"],
  ["filter rules", "you", "you", "you"],
  ["address spaces not overlapping", "n/a", "you", "n/a"],
  ["the subnet the endpoint sits in", "n/a", "n/a", "you"],
];
const kept = (i) => DECISION.filter((k) => k[i + 1] === "you").length;
const handedOff = (i) => DECISION.filter((k) => ["provider", "other side"].includes(k[i + 1])).length;
const E = [18, 17, 13, 15, 13, 8, 13];
const print = (h) => h.map((d, i) => String(d)[i ? "padStart" : "padEnd"](E[i])).join("");
console.log(print(["path", "reachable items", "latency(ms)", "period unit", "rules+lines",
  "kept", "handed off"]));
PATH.forEach(([name, item, ms, rate, fixed, lines, filters, records], i) =>
  console.log(print([name, item, ms, ((VOLUME / 100) * rate + fixed).toFixed(1),
    lines + filters + records, kept(i), handedOff(i)])));

// --- Address space overlap: peering's item that cannot be taken back -------------
// Seven networks' blocks are fictional, all in private ranges; the address arithmetic is real.
const toInt = (ip) => ip.split(".").reduce((a, o) => a * 256 + Number(o), 0);
const block = (cidr) => { const [ip, e] = cidr.split("/"); const b = 2 ** (32 - Number(e));
  const start = Math.floor(toInt(ip) / b) * b; return { start, end: start + b - 1 }; };
const overlaps = (a, b) => a.start <= b.end && b.start <= a.end;
const NETWORK = [["measurement-collector", "10.42.0.0/20"], ["data-warehouse", "10.42.16.0/20"],
  ["shared-validation", "10.0.0.0/16"], ["field-unit", "10.0.0.0/16"],
  ["partner-a", "172.31.0.0/16"], ["partner-b", "172.31.0.0/16"],
  ["archive", "10.42.0.0/16"]].map(([name, c]) => ({ name, c, ...block(c) }));
const PAIR = NETWORK.flatMap((a, i) => NETWORK.slice(i + 1).map((b) => [a, b]));
const OVERLAPPING = PAIR.filter(([a, b]) => overlaps(a, b));
const RELOCATE = [];                                  // greedy: the most-overlapping network moves first
for (let remaining = [...OVERLAPPING]; remaining.length; ) {
  const counts = new Map();
  for (const [a, b] of remaining) for (const x of [a, b]) counts.set(x, (counts.get(x) ?? 0) + 1);
  const most = [...counts.entries()].sort((p, q) => q[1] - p[1] || NETWORK.indexOf(p[0]) - NETWORK.indexOf(q[0]))[0][0];
  RELOCATE.push(most);
  remaining = remaining.filter(([a, b]) => a !== most && b !== most);
}
const RELOCATE_COST = 1604;                           // input: from this topic's first lesson
const A = [24, 17, 19, 13, 20];
const print2 = (h) => h.map((d, i) => String(d)[i ? "padStart" : "padEnd"](A[i])).join("");
console.log("\n" + print2(["network", "block", "peerable networks", "overlapping", "re-addressed"]));
for (const a of NETWORK) {
  const c = NETWORK.filter((b) => b !== a && overlaps(a, b)).length;
  console.log(print2([a.name, a.c, NETWORK.length - 1 - c, c, RELOCATE.includes(a) ? "yes" : "no"]));
}
console.log(`\npairs ${PAIR.length}; peering ${PAIR.length - OVERLAPPING.length}/${PAIR.length}, ` +
  `private link ${PAIR.length}/${PAIR.length} (address space is invisible)`);
console.log(`networks to re-address: ${RELOCATE.length} (${RELOCATE.map((x) => x.name).join(", ")}) ` +
  `= ${RELOCATE.length * RELOCATE_COST} units`);

// --- No transitivity: peering count for N networks --------------------------------
// A peering only reaches its own two ends; the reached pairs equal the direct edge count.
const TRANSIT_FIXED = 120, TRANSIT_LINK = 30;         // fictional unit
const G = [10, 14, 15, 12, 17, 15, 16, 12];
const print3 = (h) => h.map((d, i) => String(d)[i ? "padStart" : "padEnd"](G[i])).join("");
console.log("\n" + print3(["networks", "pairs needed", "star reached", "full mesh", "full mesh lines",
  "transit links", "transit lines", "unit/pair"]));
for (const n of [3, 4, 6, 8, 12]) {
  const pairs = (n * (n - 1)) / 2, fee = TRANSIT_FIXED + TRANSIT_LINK * n;
  console.log(print3([n, pairs, n - 1, pairs, n * (n - 1) * TABLES, n, (TABLES + 1) * n,
    (fee / pairs).toFixed(1)]));
}
```

```
path                reachable items  latency(ms)    period unit  rules+lines    kept   handed off
public endpoint                   1           14           48.0            3       5            1
peering                         384            2           24.0            7       6            0
private link                      1            3           49.0            1       2            4

network                             block  peerable networks  overlapping        re-addressed
measurement-collector        10.42.0.0/20                  5            1                  no
data-warehouse              10.42.16.0/20                  5            1                  no
shared-validation             10.0.0.0/16                  5            1                 yes
field-unit                    10.0.0.0/16                  5            1                  no
partner-a                   172.31.0.0/16                  5            1                 yes
partner-b                   172.31.0.0/16                  5            1                  no
archive                      10.42.0.0/16                  4            2                 yes

pairs 21; peering 17/21, private link 21/21 (address space is invisible)
networks to re-address: 3 (archive, shared-validation, partner-a) = 4812 units

networks    pairs needed   star reached   full mesh  full mesh lines  transit links   transit lines   unit/pair
3                      3              2           3               30              3              18        70.0
4                      6              3           6               60              4              24        40.0
6                     15              5          15              150              6              36        20.0
8                     28              7          28              280              8              48        12.9
12                    66             11          66              660             12              72         7.3
```

## The Bill for Three Paths

The first table's second column is this lesson's core measure: how many items become reachable
once the connection is set up.

For the public endpoint this number is one — the single endpoint the other side publishes. For
private link it is also one. For peering it is **384**: 96 instances' four ports each. Peering
does not connect a service, it connects a **network**; which service is reachable is now the job
of the filter rules, not the routing.

The bill column is unexpected. Peering is the cheapest — **24 units** — because an inter-network
fee is charged instead of the public egress fee. The public endpoint is 48 units. Private link is
the most expensive at **49 units**: its volume fee is the same as peering's, plus the endpoint's
rent stacks on top. Read side by side, the three numbers show a pattern: **the cheapest path is
the path that opens the widest surface.** The 25-unit gap between them is the price of closing off
383 items.

The rule count points the same way. Peering writes seven items: one line in each of the five
tables, plus two filter rules. All five lines are the same line; writing four and skipping one
silently drops one zone's traffic onto a different path. Private link writes a **single item**.

## The Decision Handed Off

The last two columns are this course's own measure. For the public endpoint, five of eight
decision items stay with the renter, one is the other side's; no item is handed off to a provider.
For peering, **six items stay, zero are handed off**. Peering does not hand off a single decision
— which range the route is written to, traffic's direction, name resolution, filters, and address
spaces not overlapping are all the joint work of the two sides.

Private link is the reverse: **two items stay, four sit with the provider**. No route is written —
the endpoint takes an address in one of your subnets, and the local route already covers it. Which
service is reachable is not chosen; the endpoint is bound to a single service. Direction is not
chosen either: the connection is one-way, the other side cannot connect back to you.

The two items that stay are the filter rules and which subnet the endpoint sits in. The second is
this lesson's small trap: the endpoint sits in a subnet, consumes one of its addresses, and the
subnet boundary is a previous lesson's **item that cannot be taken back**. The handoff is not a
loss but a trade: four items went, and in exchange 383 reachable items and five routing lines went
with them.

## Address Space Overlap

The second table measures peering's **item that cannot be taken back**, and it ties back to this
course's first lesson.

For two networks to be peerable, their address spaces must not overlap. If they do, the same
address corresponds to two different machines, and no routing decision can be made. In the
seven-network fictional plan there are 21 pairs, and **four cannot be peered**.

The reason reads right off the table. `shared-validation` and `field-unit` wrote the same block;
so did `partner-a` and `partner-b`. These are not mistakes but a **default**: two separate teams
left the same starting value in place, unaware of each other. The fourth overlap is different in
kind: `archive` wrote its block one bit wider and swallowed two networks from its own organization
inside it — on its own it costs two pairs.

The fix is not in routing. The peering is rejected, and no rule can force it through; the only
thing that can be done is **re-address one side**. The model produces three networks to close four
overlaps: **4,812 fictional units**. Which side gets moved is a separate decision; moving a shared
validation service is a different job from moving a field unit.

The last line gives the real comparison. Private link connects **21 of 21 pairs**. The address
spaces still overlap, but it no longer matters: the endpoint takes its own address in your subnet,
and the counterpart network's address space is never visible to you at all. This is the real thing
received in exchange for the four-item handoff.

## The Absence of Transitivity

The third table counts peering's second limit. A peering only reaches its own two ends: if A is
peered with B and B is peered with C, A and C cannot talk. The network in the middle is not a
**path**.

The star column is the result. Connecting six networks to a central network needs five peerings
and reaches **five pairs** — while what is needed is 15 pairs. Once the setup is done, every
network is connected to something, and two thirds of the pairs cannot find each other.

A full mesh solves this, and it grows **quadratically**. Six networks need 15 peerings and 150
routing lines; twelve networks need 66 peerings and **660 lines**. The line count is multiplied by
five tables, because every network has its own tables.

A central transit layer makes the count **linear**: 12 connections for twelve networks, 72 lines,
and the same 66 pairs. Its cost is in the last column, and it drops as scale grows: 70 units per
pair at three networks, 7.3 units at twelve.

## Summary

- Peering raises reachable items from one to 384 and is the cheapest path at 24 units; private
  link keeps items at one and is the most expensive at 49 units. The 25-unit gap between them is
  the price of closing off 383 items.
- Peering hands off no decision (six items stay, zero handed off); private link gives four items
  to the provider and leaves two — the filter rules and the subnet the endpoint sits in.
- In the seven-network plan, four of 21 pairs cannot be peered because of address overlap; the
  fix is re-addressing three networks, 4,812 fictional units. Private link connects 21 of 21
  pairs in the same plan.
- Because peering is not transitive, the star layout reaches only five of six networks' pairs; at
  twelve networks, a full mesh needs 660 routing lines while a central transit layer connects the
  same 66 pairs with 72 lines.

## Course Wrap-Up

| Lesson | Decision That Stays | Item That Cannot Be Taken Back | Surface Opened or Its Cost |
|---|---|---|---|
| Virtual Machine Instances | 6/11 items, family and size | 3 items: architecture, subnet, encryption | 5.3 hours of fleet renewal |
| Machine Images | 6/9 items, embedding level | 3 items: published image, embedded secret | 1,161 minutes of bake load |
| Persistent and Interruptible Capacity | 5/9 items, job type match | 3 items: unsaved work | 2.40× duration |
| Launch Templates | 5/8 items, field defaults | 6 fields: image, subnet, script | 11/12 fields overridden |
| Auto Scaling Groups | 6/9 items, threshold and cooldown | 3 items: unhealthy stamp | 276 launches a day |
| Managed Container Services | 3/15 items, task scaling | 3 items: task definition version | 234 hours of exit |
| Virtual Private Cloud | 8/12 items, prefix length | 2 items: block and placement | 1,604 units to rebuild |
| Subnets | 5 items, slice size and zone | 1 item: subnet boundary | 6 components, 5 tables |
| Route Tables | 3 items, rule width | 490 volume units, swallowed measurement | 266 units of wrong egress |
| Internet and Address Translation Gateways | 4 items, gateway count and placement | 1,848 external log entries | 101% connection fill |
| Security Groups and Network Access Lists | 4 items, mechanism and order | double-recorded measurement | 9 rules, 2 escaped flows |
| Load Balancers | 9 items, layer and threshold | 1 item: the balancer's layer | 7 termination points |
| Persistent Address and Name Integration | 6 items, address layout | released address | 4,875 requests to a stranger |
| Content Delivery Network | 9/15 items, cache key | published response | 3,600 seconds on the client |
| Private Connectivity and Peering | 6 items under peering, 2 under private link | address space overlap | 384 reachable items |

The second column writes this course's rule: **even in a rented layer, a portion of the decisions
stays with you; knowing which of them cannot be undone determines more than the rental decision
itself.** Even in the lesson with the highest handoff rate, three items stayed with the renter, and
three items that cannot be undone stood alongside them.

The third column gathers into four clusters. **Address space and its boundary** in four lessons:
the block itself, the subnet boundary, the subnet an instance lands on, and the overlap that
blocks peering. **A definition fixed at creation** in four lessons: the published image, the
startup script, the task definition version, the balancer's layer. **A trace that has escaped
outward** in three lessons: the gateway's external log entries, the released address, the
published response — all three living somewhere outside your control. **Work lost or repeated** in
four lessons: the interrupted instance's unsaved work, what the terminated instance was holding,
the swallowed measurement, the double record.

None of the four clusters is a line on a bill. In none of the fifteen lessons did the item that
cannot be undone produce a warning; every one of them was written silently on setup day, and its
cost was measured periods later.

The machine was rented, scaled, and partly handed off; the network was split, routed, filtered,
balanced, and moved to the edge. What runs on top of them, though — the **data** — still has not
settled anywhere; measurement records and nightly digests passed through this course only as
traffic. **Storage and Data in the Cloud** takes up that data and asks the same question: which
decision is handed off when data is rented, and which item, once written, never changes again?
