ЁЯПл The SchoolтА║ЁЯЦея╕П EC2тА║ЁЯТ╛ рдзрдбрд╛ 04 тАФ Storage тАФ EBS рдЖрдгрд┐ snapshots: рдбреНрд░реЙрд╡рд░, рдЦрд░рдбрд╡рд╣реА рдЖрдгрд┐ рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рдд
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯТ╛ рдзрдбрд╛ 04 тАФ Storage тАФ EBS рдЖрдгрд┐ snapshots: рдбреНрд░реЙрд╡рд░, рдЦрд░рдбрд╡рд╣реА рдЖрдгрд┐ рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рдд

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 04 ┬╖ рдорд╛рдЧреЗ: lesson-03-amis-launch ┬╖ рдкреБрдвреЗ: lesson-05-networking


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ03, рдЖрдгрд┐ рдбреЗрд╕реНрдХ рдЖрдкрд▓реНрдпрд╛ рд╡рд╕реНрддреВ рдХреБрдареЗ рдареЗрд╡рддреЛ рддреЗ: EBS volumes (рдХреБрд▓реВрдк рд▓рд╛рд╡рддрд╛ рдпреЗрдгрд╛рд░рд╛ рдбреНрд░реЙрд╡рд░), instance store (рдЦрд░рдбрд╡рд╣реА), рдЖрдгрд┐ snapshots (рдЖрдЧ рди рд▓рд╛рдЧрдгрд╛рд▒реНрдпрд╛ archive рдордзрд▓реА рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рдд) тАФ reboot, stop рдЖрдгрд┐ terminate рдирдВрддрд░ рдХрд╛рдп рдЯрд┐рдХрддреЗ рдпрд╛рдЪреНрдпрд╛ table рд╕рд╣, рдЖрдгрд┐ ec2/costs.py рдордзрд▓реЗ snapshot_cost().

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдкреНрд░рддреНрдпреЗрдХ рдбреЗрд╕реНрдХрд╡рд░ рд╡рд╕реНрддреВ рдареЗрд╡рдгреНрдпрд╛рдЪреНрдпрд╛ рддреАрди рдЬрд╛рдЧрд╛ рдЕрд╕рддрд╛рдд.

рдбреНрд░реЙрд╡рд░ ЁЯТ╛ (рдПрдХ EBS volume) рд╣рд╛ рдХреБрд▓реВрдк рд▓рд╛рд╡рддрд╛ рдпреЗрдгрд╛рд░рд╛ рдбреНрд░реЙрд╡рд░ рдЖрд╣реЗ, рдЬреЛ рддреНрдпрд╛рдЪ рдЗрдорд╛рд░рддреАрддрд▓реНрдпрд╛ рднрд╛рдВрдбрд╛рд░рд╛рддреВрди рддреБрдордЪреНрдпрд╛ рдбреЗрд╕реНрдХрдкрд░реНрдпрдВрдд рдЪрд╛рдХрд╛рдВрд╡рд░реВрди рдЖрдгрд▓рд╛ рдЬрд╛рддреЛ. рддреБрдореНрд╣реА рд░рд╛рддреНрд░реА рдбреЗрд╕реНрдХ рд╕реЛрдбреВрди рдЧреЗрд▓рд╛рдд (stop), рддрд░реА рдбреНрд░реЙрд╡рд░ рднрд░рд▓реЗрд▓рд╛рдЪ рд░рд╛рд╣рддреЛ. рдбреЗрд╕реНрдХ рдлреЗрдХреВрди рджрд┐рд▓рд╛ (terminate), рддрд░ рдореБрдЦреНрдп рдбреНрд░реЙрд╡рд░ рд╕рд╣рд╕рд╛ рддреНрдпрд╛рдЪреНрдпрд╛рд╕реЛрдмрдд рдЬрд╛рддреЛ тАФ рдкрдг рддреБрдореНрд╣реА рд╕реНрд╡рддрдГ рдЬреЛрдбрд▓реЗрд▓рд╛ рдЬрд╛рд╕реНрддреАрдЪрд╛ рдбреНрд░реЙрд╡рд░ рднрд░рд▓реЗрд▓реНрдпрд╛ рдЕрд╡рд╕реНрдереЗрддрдЪ рднрд╛рдВрдбрд╛рд░рд╛рдд рдкрд░рдд рдиреЗрд▓рд╛ рдЬрд╛рддреЛ.

рдЦрд░рдбрд╡рд╣реА ЁЯУЭ (instance store) рдбреЗрд╕реНрдХрдЪреНрдпрд╛ рд╡рд░рдЪреНрдпрд╛ рднрд╛рдЧрд╛рддрдЪ рдмрд╕рд╡рд▓реЗрд▓реА рдЕрд╕рддреЗ. рддреА рдЦреВрдк рд╡реЗрдЧрд╡рд╛рди рдЖрд╣реЗ, рдореЛрдлрдд рдЖрд╣реЗ, рдЖрдгрд┐ рддреБрдореНрд╣реА рдбреЗрд╕реНрдХ рд╕реЛрдбрддрд╛ рддреЗрд╡реНрд╣рд╛ рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рдкреБрд╕рд▓реА рдЬрд╛рддреЗ. рдХрдЪреНрдЪреНрдпрд╛ рдХрд╛рдорд╛рд╕рд╛рдареА рдЙрддреНрддрдо, рддреБрдордЪреНрдпрд╛ рдЧреГрд╣рдкрд╛рдард╛рд╕рд╛рдареА рдЕрдЧрджреА рд╡рд╛рдИрдЯ.

рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рдд ЁЯУ╕ (рдПрдХ snapshot) рдореНрд╣рдгрдЬреЗ рдЖрдЧ рди рд▓рд╛рдЧрдгрд╛рд▒реНрдпрд╛ archive рдордзреНрдпреЗ рдареЗрд╡рд▓реЗрд▓реА рдбреНрд░реЙрд╡рд░рдЪреА copy. рдкрд╣рд┐рд▓реА рдкреНрд░рдд рд╕рдЧрд│реЗ copy рдХрд░рддреЗ; рддреНрдпрд╛рдирдВрддрд░ рдлрдХреНрдд рдмрджрд▓рд▓реЗрд▓реА рдкрд╛рдиреЗ. рдЖрдгрд┐ рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рддреАрдЪреЗ рдЬрд┐рд▓реНрд╣реНрдпрд╛рддрд▓реНрдпрд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рдЗрдорд╛рд░рддреАрдд рдкреБрдиреНрд╣рд╛ рдбреНрд░реЙрд╡рд░ рдмрдирд╡рддрд╛ рдпреЗрддреЗ тАФ рдЬрд░реА рддреЛ рдбреНрд░реЙрд╡рд░ рд╕реНрд╡рддрдГ рдиреЗрд╣рдореА рдПрдХрд╛рдЪ рдЗрдорд╛рд░рддреАрдд рд░рд╛рд╣рд┐рд▓рд╛ рдЕрд╕рд▓рд╛ рддрд░реА.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    desk["ЁЯЦея╕П desk in AZ-a"]
    root["ЁЯТ╛ root EBS<br/>DeleteOnTermination = true"]
    data["ЁЯТ╛ data EBS<br/>attached later"]
    pad["ЁЯУЭ instance store"]
    desk --- root
    desk --- data
    desk --- pad
    snap["ЁЯУ╕ snapshot<br/>6 GB first + 0.5 GB/day changed"]
    data -->|"1 photocopy, incremental"| snap
    newvol["ЁЯТ╛ new volume in AZ-b"]
    snap -->|"2 restore anywhere in the Region"| newvol
    rules["ЁЯФБ reboot: all kept ┬╖ тП╕я╕П stop: pad wiped ┬╖ ЁЯЧСя╕П terminate: root deleted, data kept, pad wiped"]
    desk -.->|"3"| rules

ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/ec2/lesson-diagrams.html#l04

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг "data рдХреБрдареЗ рд░рд╛рд╣рддреЛ?" рдпрд╛рд╡рд░реВрди stop, crash рдХрд┐рдВрд╡рд╛ terminate рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд┐рддреА рдорд╣рд╛рдЧрд╛рдд рдкрдбреЗрд▓ рддреЗ рдард░рддреЗ. EC2 рд╡рд░рдЪреНрдпрд╛ data рд╣рд░рд╡рдгреНрдпрд╛рдЪреНрдпрд╛ рдмрд╣реБрддреЗрдХ рдХрдерд╛ рдпрд╛ рддрд┐рдШрд╛рдВрдкреИрдХреА рдПрдХ рдЕрд╕рддрд╛рдд: database instance store рд╡рд░ рд╣реЛрддрд╛, root volume instance рд╕реЛрдмрдд delete рдЭрд╛рд▓рд╛, рдХрд┐рдВрд╡рд╛ рдХреЛрдгреА рдХрдзреА snapshot рдШреЗрддрд▓рд╛рдЪ рдирд╛рд╣реА. рдЖрдгрд┐ stopped рдбреЗрд╕реНрдХ рдореЛрдлрдд рдирд╕рддреЛ: рддреНрдпрд╛рдЪреНрдпрд╛ рдбреНрд░реЙрд╡рд░рдЪреЗ рдмрд┐рд▓ рдЪрд╛рд▓реВрдЪ рд░рд╛рд╣рддреЗ.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

ec2/demo.py рдордзрд▓реЗ storage() root EBS volume (DeleteOnTermination = true рд╕рд╣), рдПрдХ рдЬрд╛рд╕реНрддреАрдЪрд╛ data volume рдЖрдгрд┐ рдПрдХ instance store рдпрд╛рдВрдЪреА рдЯрд┐рдХрдгреНрдпрд╛рдЪреА table рдЫрд╛рдкрддреЗ, рдордЧ ec2/costs.py рдордзрд▓реЗ costs.snapshot_cost() call рдХрд░рддреЗ: рдкрд╣рд┐рд▓реА copy рд╡рд╛рдкрд░рд▓реЗрд▓реЗ blocks рд╕рд╛рдард╡рддреЗ, рддреНрдпрд╛рдирдВрддрд░рдЪреА рдкреНрд░рддреНрдпреЗрдХ рдлрдХреНрдд рдмрджрд▓рд▓реЗрд▓реЗ blocks. Compute hours рд╢реВрдиреНрдп рдЕрд╕рд▓реЗ рддрд░реА costs.monthly() gp3 storage рдЪреЗ рдмрд┐рд▓ рд▓рд╛рд╡рддреЗ. рдХрд┐рдорддреА рдЕрдВрджрд╛рдЬреЗ рдЖрд╣реЗрдд.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 ec2/demo.py storage
python3 - <<'EOF'
import sys; sys.path.insert(0, "ec2"); import costs
# a busier disk: 20 GB used, 2 GB changes a day тАФ how much does the retention period cost?
print("keep 30 days:", costs.snapshot_cost(changed_gb_per_day=2, days_kept=30, first_full_gb=20), "(GB stored, $/month)")
print("keep  7 days:", costs.snapshot_cost(changed_gb_per_day=2, days_kept=7, first_full_gb=20))
# a stopped desk: zero compute hours, the 20 GB gp3 volume still bills
print("stopped all month (compute $, disk $):", costs.monthly("t3.micro", hours=0, gp3_gb=20))
EOF

рдЦрд▒реНрдпрд╛ account рд╡рд░ (AWS credentials рд▓рд╛рдЧрддрд╛рдд; volumes рдЖрдгрд┐ snapshots рддреБрдореНрд╣реА delete рдХрд░реЗрдкрд░реНрдпрдВрдд рдмрд┐рд▓ рд▓рд╛рд╡рддрд╛рдд тАФ рддреБрдордЪреНрдпрд╛ account рдордзрд▓реЗ рдЦрд░реЗ IDs рд╡рд╛рдкрд░рд╛):

aws ec2 create-volume --availability-zone us-east-1a --size 20 --volume-type gp3 --encrypted
aws ec2 attach-volume --volume-id vol-0123456789abcdef0 --instance-id i-0123456789abcdef0 --device /dev/sdf
aws ec2 create-snapshot --volume-id vol-0123456789abcdef0 --description "before the upgrade"
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[].[SnapshotId,VolumeSize,State,StartTime]' --output table
aws ec2 enable-ebs-encryption-by-default --region us-east-1

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

рдЯрд┐рдХрдгреНрдпрд╛рдЪреА table рдЕрд╢реА рджрд┐рд╕рддреЗ: reboot тЬЕ тЬЕ тЬЕ; stop / start тЬЕ тЬЕ тЭМ wiped; terminate тЭМ deleted тЬЕ kept тЭМ wiped. рдордЧ 6 GB first copy + 0.5 GB changed/day ├Ч 6 more days = 9.0 GB stored тЙИ $0.45/month тАФ 6 GB disk рдЪреЗ рдЖрдард╡рдбрд╛рднрд░ рд░реЛрдЬ рдШреЗрддрд▓реЗрд▓реЗ snapshots 9 GB рд╕рд╛рдард╡рддрд╛рдд, 42 рдирд╛рд╣реА. рддреБрдордЪрд╛ snippet рдЫрд╛рдкрддреЛ keep 30 days: (78, 3.9), keep 7 days: (32, 1.6) рдЖрдгрд┐ stopped all month (compute $, disk $): (0.0, 1.6) тАФ compute рд╢реВрдиреНрдп, рдкрдг рдбреНрд░реЙрд╡рд░рдЪрд╛ рдЦрд░реНрдЪ рдЕрдЬреВрдирд╣реА $1.60.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ storage рдмрджреНрджрд▓ рддреБрдореНрд╣реА рд╕рд╛рдВрдЧреВ рд╢рдХрддрд╛ рдХреА reboot, stop рдЖрдгрд┐ terminate рддреНрдпрд╛рдЪреЗ рдХрд╛рдп рдХрд░рддрд╛рдд тАФ рдЖрдгрд┐ рд░реЛрдЬрдЪреНрдпрд╛ рд╕рд╛рдд рдЭреЗрд░реЙрдХреНрд╕ рдкреНрд░рддреА рд╕рд╛рдд рдкреВрд░реНрдг copies рдкреЗрдХреНрд╖рд╛ рдЦреВрдк рдХрдореА рдЦрд░реНрдЪрд╛рдЪреНрдпрд╛ рдХрд╛ рдЕрд╕рддрд╛рдд.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: "data EBS рд╡рд░ рдЖрд╣реЗ рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ snapshots рдЖрд╣реЗрдд" рд╣рд╛ рдкреНрд░рддреНрдпреЗрдХ reviewer рддрдкрд╛рд╕рддреЛ рддреЛ рдкрд╛рдпрд╛ рдЖрд╣реЗ, рд╕реЛрдмрдд encryption by default рдЪрд╛рд▓реВ, gp2 рдРрд╡рдЬреА gp3, рдЖрдгрд┐ рдПрдХ retention policy (рдзрдбрд╛ 12), рдореНрд╣рдгрдЬреЗ snapshots рдирд╛ рдирд╛рд╣реАрд╕реЗ рд╣реЛрддрд╛рдд рдирд╛ рдХрд╛рдпрдордЪреЗ рд╕рд╛рдардд рд░рд╛рд╣рддрд╛рдд.

тПня╕П рдкреБрдвреЗ

рдбреЗрд╕реНрдХрдЬрд╡рд│ рдХреЛрдгрд╛рд▓рд╛ рдпреЗрдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рдЖрд╣реЗ? рдбреЗрд╕реНрдХрд╡рд░рдЪреА рдкрд╛рд╣реБрдгреНрдпрд╛рдВрдЪреА рдпрд╛рджреА рдЖрдгрд┐ рд╡рд┐рдВрдЧрдЪреНрдпрд╛ рджрд╛рд░рд╛рд╡рд░рдЪреЗ рдирд┐рдпрдо тАФ security groups рдЖрдгрд┐ network ACLs.

git checkout lesson-05-networking

ЁЯТ╛ Lesson 04 тАФ Storage тАФ EBS & snapshots: the drawer, the scratch pad and the photocopy

ЁЯУН You are here: Lesson 04 of 12 ┬╖ Previous: lesson-03-amis-launch ┬╖ Next: lesson-05-networking


ЁЯУж What's in this branch

Lessons 01тАУ03, plus where a desk keeps its things: EBS volumes (the lockable drawer), instance store (the scratch pad), and snapshots (the photocopy in the fireproof archive) тАФ with a table of what survives reboot, stop and terminate, and snapshot_cost() in ec2/costs.py.

ЁЯзТ Explain like I'm 5

Every desk has three places to keep things.

The drawer ЁЯТ╛ (an EBS volume) is a lockable drawer that is wheeled up to your desk from the storeroom in the same building. If you leave the desk for the night (stop), the drawer stays full. If the desk is thrown away (terminate), the main drawer usually goes with it тАФ but an extra drawer you attached yourself is wheeled back to the storeroom, still full.

The scratch pad ЁЯУЭ (the instance store) is built into the desk top. It is very fast, it is free, and it is wiped every time you leave the desk. Great for rough work, terrible for your homework.

The photocopy ЁЯУ╕ (a snapshot) is a copy of a drawer kept in the fireproof archive. The first copy copies everything; after that, only the pages that changed. And a photocopy can be turned back into a drawer in any building in the district тАФ even though the drawer itself only ever lived in one.

ЁЯЧ║я╕П Diagram

flowchart LR
    desk["ЁЯЦея╕П desk in AZ-a"]
    root["ЁЯТ╛ root EBS<br/>DeleteOnTermination = true"]
    data["ЁЯТ╛ data EBS<br/>attached later"]
    pad["ЁЯУЭ instance store"]
    desk --- root
    desk --- data
    desk --- pad
    snap["ЁЯУ╕ snapshot<br/>6 GB first + 0.5 GB/day changed"]
    data -->|"1 photocopy, incremental"| snap
    newvol["ЁЯТ╛ new volume in AZ-b"]
    snap -->|"2 restore anywhere in the Region"| newvol
    rules["ЁЯФБ reboot: all kept ┬╖ тП╕я╕П stop: pad wiped ┬╖ ЁЯЧСя╕П terminate: root deleted, data kept, pad wiped"]
    desk -.->|"3"| rules

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/ec2/lesson-diagrams.html#l04

тЭУ What

ЁЯдФ Why

Because "where does the data live?" decides what a stop, a crash or a terminate costs you. Most data-loss stories on EC2 are one of three: the database was on instance store, the root volume was deleted with the instance, or nobody ever took a snapshot. And a stopped desk is not free: its drawers keep billing.

ЁЯФз How (in this repo)

storage() in ec2/demo.py prints the survival table for a root EBS volume (with DeleteOnTermination = true), an extra data volume and an instance store, then calls costs.snapshot_cost() from ec2/costs.py: the first copy stores the used blocks, every later one only the changed blocks. costs.monthly() bills gp3 storage even when compute hours are zero. The prices are approximate.

ЁЯзк Try it

python3 ec2/demo.py storage
python3 - <<'EOF'
import sys; sys.path.insert(0, "ec2"); import costs
# a busier disk: 20 GB used, 2 GB changes a day тАФ how much does the retention period cost?
print("keep 30 days:", costs.snapshot_cost(changed_gb_per_day=2, days_kept=30, first_full_gb=20), "(GB stored, $/month)")
print("keep  7 days:", costs.snapshot_cost(changed_gb_per_day=2, days_kept=7, first_full_gb=20))
# a stopped desk: zero compute hours, the 20 GB gp3 volume still bills
print("stopped all month (compute $, disk $):", costs.monthly("t3.micro", hours=0, gp3_gb=20))
EOF

On a real account (needs AWS credentials; volumes and snapshots bill until you delete them тАФ use real IDs from your account):

aws ec2 create-volume --availability-zone us-east-1a --size 20 --volume-type gp3 --encrypted
aws ec2 attach-volume --volume-id vol-0123456789abcdef0 --instance-id i-0123456789abcdef0 --device /dev/sdf
aws ec2 create-snapshot --volume-id vol-0123456789abcdef0 --description "before the upgrade"
aws ec2 describe-snapshots --owner-ids self --query 'Snapshots[].[SnapshotId,VolumeSize,State,StartTime]' --output table
aws ec2 enable-ebs-encryption-by-default --region us-east-1

тЬЕ Verify тАФ what you should see

The survival table reads: reboot тЬЕ тЬЕ тЬЕ; stop / start тЬЕ тЬЕ тЭМ wiped; terminate тЭМ deleted тЬЕ kept тЭМ wiped. Then 6 GB first copy + 0.5 GB changed/day ├Ч 6 more days = 9.0 GB stored тЙИ $0.45/month тАФ a week of daily snapshots of a 6 GB disk stores 9 GB, not 42. Your snippet prints keep 30 days: (78, 3.9), keep 7 days: (32, 1.6) and stopped all month (compute $, disk $): (0.0, 1.6) тАФ zero compute, but the drawer still costs $1.60.

ЁЯПБ What you just proved

You can say, for each kind of storage, what a reboot, a stop and a terminate do to it тАФ and why seven daily photocopies cost far less than seven full copies.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: "the data is on EBS and snapshotted" is the baseline every reviewer checks, with encryption by default on, gp3 instead of gp2, and a retention policy (lesson 12) so snapshots neither vanish nor pile up forever.

тПня╕П Next

Who is allowed to walk up to the desk? The guest list at the desk and the rules on the wing door тАФ security groups and network ACLs.

git checkout lesson-05-networking
тЖР Previousamis launchNext тЖТnetworking

This page is the lesson's README from the lesson-04-storage branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.