Basics of pacemaker
pacemaker components diagram anatomy cardiac

This visual content features a 3-dimensional transesophageal echocardiographic (3D TEE) image of the tricuspid valve, accompanied by a schematic diagram for anatomical orientation. The image shows an 'en face' surgeon’s view of the tricuspid valve from the right atrium perspective. Key anatomical components identified in the schematic and 3D volume include the anterior, posterior, and septal leaflets. Two distinct medical devices are visible passing through the valve orifice: a pacemaker lead (PML), highlighted by a red circle, and a pulmonary artery catheter (PAC), highlighted by a blue circle. The PML is strategically positioned at the septal-posterior (SP) commissure, appearing closely associated with the valve annulus in that region. Conversely, the PAC is located between the anterior-posterior (AP) leaflets. This diagnostic imaging demonstrates the spatial relationship between multiple intracardiac devices and the tricuspid valve anatomy, serving as an educational resource for perioperative monitoring and understanding device-related interference or positioning during cardiac procedures.

Anatomical diagram illustrating the configuration for Prolonged Temporary Cardiac Pacing (PTCP). The illustration shows a human torso with a focus on the cardiovascular and pacing systems. A silver-colored, single-chamber pacemaker generator is positioned externally on the patient's upper right chest, secured to the skin. An active-fixation lead is connected to the generator and enters the venous system via a percutaneous puncture of the right internal jugular vein. The lead is shown descending through the superior vena cava, entering the heart, and terminating with its tip anchored in the apex of the right ventricle. The diagram highlights the clinical pathway for temporary pacing in patients with transient conduction disorders or those with contraindications to permanent implantation, such as active infection. Key components depicted include the external pulse generator, the transvenous lead, the jugular venous access site, and the intracardiac positioning within the right ventricular cavity.

This anatomical diagram presents two views—frontal (left) and left lateral (right)—of the Dassault Systèmes Living Heart Human Model (LHHM), a high-fidelity 3D computational representation used for cardiovascular device evaluation. The model uses color-coded translucency to display internal and external structures: the left atrium is shown in purple, the aorta in light blue, and other major superior vessels in green and cream. Fine light-blue vessels representing coronary arteries are visible on the ventricular surface. A key educational feature is the placement of a leadless pacemaker, depicted as an elongated, dark-gray rectangular component. The device is strategically positioned in the apex region of the left ventricle. In the frontal view, the pacemaker is visible through the translucent ventricular wall, while the left lateral view clarifies its vertical orientation along the apical endocardium. This visualization demonstrates the spatial relationship between intracardiac medical devices and 3D cardiac anatomy in a simulated physiological environment.

This composite educational graphic illustrates two common approaches for Temporary Permanent Pacemakers (TPPM). The top panel features anatomical diagrams showing venous access routes: the left diagram demonstrates the subclavian approach with a lead entering the left subclavian vein and progressing toward the right atrium and ventricle; the right diagram shows the internal jugular approach with a lead entering via the neck. The bottom panel contains clinical photographs of these procedures. In both cases, an external pacemaker generator is positioned on the patient's upper chest wall, secured to the skin with transparent adhesive dressings. One photograph shows the insertion site covered with a bulky white gauze dressing (left), while the other shows the use of a circular adhesive stabilizing device and a transparent dressing (right). This visual aid is designed for medical education, specifically in cardiovascular surgery and intensive care, to demonstrate lead management, insertion anatomy, and securement techniques for temporary cardiac pacing.
pacemaker NBG code modes VVI DDD cardiac pacing ECG

A comparative 12-lead electrocardiogram (ECG) showing cardiac rhythm changes before and after atrial lead implantation. Panel (a) displays a rhythm with intermittent ventricular pacing (VVI mode). It features wide, bizarre QRS complexes (1st–4th, 6th, 8th, and 10th beats) indicative of ventricular pacing spikes and subsequent ventricular depolarization, interspersed with narrower, intrinsic QRS complexes (5th, 7th, 9th–11th beats). There is a notable lack of consistent atrioventricular (AV) synchrony in this panel. Panel (b) demonstrates the results of dual-chamber pacing (AAI/DDD mode) after new atrial lead placement. This strip shows restored AV synchrony, where each atrial deflection (P-wave) is consistently followed by a narrow, intrinsic ventricular deflection. This comparison illustrates the transition from asynchronous ventricular pacing to synchronized atrial-driven ventricular activation, highlighting the resolution of AV desynchronization. Key clinical concepts shown include pacing morphology, intrinsic conduction, and the importance of AV synchrony in pacemaker management.

A comparison of three transthoracic echocardiography (TTE) panels demonstrating mitral inflow Doppler patterns in different cardiac pacing states. Each panel contains a grayscale apical four-chamber view (top) and a corresponding pulsed-wave Doppler recording (bottom) with concurrent electrocardiogram (ECG) tracing. Panel (a) shows atrioventricular (AV) desynchronization during VVI pacing, characterized by 'EA fusion' where the early diastolic (E-wave) and atrial contraction (A-wave) peaks are merged into a single broad envelope, indicating suboptimal ventricular filling. Panel (b) illustrates partial separation of E and A waves during intermittent intrinsic ventricular deflections. Panel (c) demonstrates restored AV synchrony during DDD pacing mode after new atrial lead implantation; the Doppler recording shows distinct, separated E and A wave peaks (outlined in white), representing physiological diastolic filling. This visual comparison highlights the impact of pacemaker programming and lead placement on left ventricular hemodynamics and diastolic performance in patients with AV desynchronization.

This diagnostic image is a standard 12-lead electrocardiogram (ECG) printed on grid paper, demonstrating dual-chamber (DDD) cardiac pacing. The layout includes limb leads (I, II, III, aVR, aVL, aVF) and precordial leads (V1-V6) arranged in a multi-channel format, with a rhythm strip of Lead II at the bottom. The tracing clearly shows distinct vertical pacemaker spikes occurring in a sequential manner. The first spike (atrial spike) precedes the P-wave, followed by a second spike (ventricular spike) immediately preceding the QRS complex, indicating an AV-sequential pacing mode. The QRS complexes exhibit a widened morphology with a left bundle branch block-like pattern, particularly visible in the precordial leads, which is characteristic of right ventricular apical pacing. This ECG serves as an educational example for identifying artificial pacemaker activity, understanding dual-chamber pacing logic, and recognizing the morphology of paced cardiac rhythms in clinical practice.
| Type | Description | Notes |
|---|---|---|
| Unipolar | Negative electrode at lead tip (cathode); pulse generator casing = anode | Prone to oversensing myopotentials and EMI; not compatible with ICD |
| Bipolar | Both electrodes within the heart (~2 cm apart) | Preferred; less susceptible to interference |
| Position | Letter | Meaning | Options |
|---|---|---|---|
| I | Chamber Paced | Where the stimulus is delivered | A (Atrium), V (Ventricle), D (Dual), O (None) |
| II | Chamber Sensed | Where intrinsic activity is detected | A, V, D, O |
| III | Response to sensing | What the pacemaker does when it senses | I (Inhibited), T (Triggered), D (Dual), O (None) |
| IV | Rate modulation | Programmability / rate-adaptive function | R (Rate modulation), M (Multi), C (Communicating), O (None) |
| V | Antitachycardia function | Shock or overdrive pacing | P (Antitachycardia pacing), S (Shock), D (Dual), O (None) |
| Mode | Meaning | Use |
|---|---|---|
| VOO | Pace ventricle, no sensing, no response | Asynchronous (fixed rate); used with magnet |
| VVI | Pace & sense ventricle, inhibit if sensed | Simplest demand pacing; AF with bradycardia |
| AAI | Pace & sense atrium, inhibit if sensed | Sinus node dysfunction with intact AV conduction |
| DDD | Pace & sense both chambers, dual response | Most physiologic; maintains AV synchrony |
| VVIR | VVI + rate modulation | Active patients with chronotropic incompetence |
| DDDR | DDD + rate modulation | Optimal for most patients |


| Malfunction | ECG Finding | Common Cause |
|---|---|---|
| Failure to capture | Spike with no complex | Lead displacement, threshold rise |
| Undersensing | Pacing despite intrinsic beats | Lead displacement |
| Oversensing | No pacing when needed | Myopotentials, EMI |
| Runaway pacemaker | Very rapid rate | Circuit failure (rare) |
| Feature | Temporary | Permanent |
|---|---|---|
| Indication | Acute bradycardia, bridge to permanent, post-op | Chronic indications |
| Generator | External | Implanted subcutaneously (pectoral region) |
| Access | Internal jugular, subclavian, femoral vein | Subclavian or cephalic vein |
| Lead fixation | Passive (floats in RV) | Active or passive fixation |
| Duration | Days to weeks | Years |

Create a study guide PDF on pacemaker programming and troubleshooting
mkdir -p /tmp/workspace/pacemaker-study-guide && ls /tmp/workspace/pacemaker-study-guide/
~/pacemaker-study-guide/generate_pdf.py
#!/usr/bin/env python3
"""
Pacemaker Programming & Troubleshooting - Study Guide PDF
Generated with ReportLab
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.platypus.flowables import BalancedColumns
from reportlab.lib.colors import HexColor
from reportlab.graphics.shapes import Drawing, Rect, String
from reportlab.platypus import KeepInFrame
# ─── Colour Palette ────────────────────────────────────────────────────────
NAVY = HexColor("#1A3557")
TEAL = HexColor("#0E7490")
LIGHT_BLU = HexColor("#E0F2FE")
ACCENT = HexColor("#F59E0B")
GREEN = HexColor("#16A34A")
RED = HexColor("#DC2626")
ORANGE = HexColor("#EA580C")
GREY_BG = HexColor("#F8FAFC")
GREY_TXT = HexColor("#475569")
WHITE = colors.white
BLACK = colors.black
OUTPUT = "/tmp/workspace/pacemaker-study-guide/Pacemaker_Programming_Troubleshooting_Study_Guide.pdf"
# ─── Document Setup ─────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=1.8*cm, leftMargin=1.8*cm,
topMargin=2.2*cm, bottomMargin=2.2*cm,
title="Pacemaker Programming & Troubleshooting Study Guide",
author="Medical Study Guide",
subject="Cardiology – Pacemaker Programming and Troubleshooting"
)
W, H = A4
CONTENT_W = W - 3.6*cm
# ─── Styles ─────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def style(name, parent="Normal", **kw):
s = ParagraphStyle(name, parent=base[parent], **kw)
return s
COVER_TITLE = style("CoverTitle", fontSize=28, textColor=WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=34, spaceAfter=8)
COVER_SUB = style("CoverSub", fontSize=14, textColor=HexColor("#BAE6FD"),
alignment=TA_CENTER, fontName="Helvetica", leading=20)
COVER_TAG = style("CoverTag", fontSize=11, textColor=HexColor("#FDE68A"),
alignment=TA_CENTER, fontName="Helvetica-Oblique", leading=16)
SEC_H1 = style("SecH1", fontSize=15, textColor=WHITE, fontName="Helvetica-Bold",
leading=20, spaceAfter=4, spaceBefore=16,
backColor=NAVY, leftIndent=-6, rightIndent=-6,
borderPad=6)
SEC_H2 = style("SecH2", fontSize=12, textColor=NAVY, fontName="Helvetica-Bold",
leading=16, spaceAfter=4, spaceBefore=12, borderPad=0)
SEC_H3 = style("SecH3", fontSize=10.5, textColor=TEAL, fontName="Helvetica-Bold",
leading=14, spaceAfter=2, spaceBefore=8)
BODY = style("Body", fontSize=9.5, textColor=HexColor("#1E293B"),
fontName="Helvetica", leading=14, spaceAfter=4, alignment=TA_JUSTIFY)
BODY_BOLD = style("BodyBold", fontSize=9.5, textColor=BLACK,
fontName="Helvetica-Bold", leading=14, spaceAfter=4)
BULLET = style("Bullet", fontSize=9.5, textColor=HexColor("#1E293B"),
fontName="Helvetica", leading=14, leftIndent=14,
firstLineIndent=-10, spaceAfter=3)
BULLET2 = style("Bullet2", fontSize=9, textColor=GREY_TXT,
fontName="Helvetica", leading=13, leftIndent=26,
firstLineIndent=-10, spaceAfter=2)
NOTE = style("Note", fontSize=8.5, textColor=HexColor("#1E3A5F"),
fontName="Helvetica-Oblique", backColor=LIGHT_BLU,
leading=13, leftIndent=8, rightIndent=8,
spaceBefore=6, spaceAfter=6, borderPad=6)
WARN = style("Warn", fontSize=8.5, textColor=HexColor("#7C2D12"),
fontName="Helvetica-Oblique", backColor=HexColor("#FEF3C7"),
leading=13, leftIndent=8, rightIndent=8,
spaceBefore=6, spaceAfter=6, borderPad=6)
TIP = style("Tip", fontSize=8.5, textColor=HexColor("#14532D"),
fontName="Helvetica-Oblique", backColor=HexColor("#DCFCE7"),
leading=13, leftIndent=8, rightIndent=8,
spaceBefore=6, spaceAfter=6, borderPad=6)
TABLE_HEADER = style("TblH", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=13)
TABLE_CELL = style("TblC", fontSize=8.5, textColor=HexColor("#1E293B"),
fontName="Helvetica", leading=13, alignment=TA_LEFT)
TABLE_CELL_C = style("TblCC", fontSize=8.5, textColor=HexColor("#1E293B"),
fontName="Helvetica", leading=13, alignment=TA_CENTER)
PAGE_NUM = style("PageNum", fontSize=8, textColor=GREY_TXT,
fontName="Helvetica", alignment=TA_CENTER)
MNEMONIC = style("Mnemonic", fontSize=11, textColor=NAVY,
fontName="Helvetica-Bold", alignment=TA_CENTER, leading=18)
# ─── Helper Flowables ────────────────────────────────────────────────────────
def h1(text):
return [Spacer(1, 6), Paragraph(f" {text}", SEC_H1), Spacer(1, 4)]
def h2(text):
return [Paragraph(text, SEC_H2)]
def h3(text):
return [Paragraph(text, SEC_H3)]
def para(text, sty=BODY):
return [Paragraph(text, sty)]
def bullet(text, level=1):
s = BULLET if level == 1 else BULLET2
marker = "•" if level == 1 else "–"
return [Paragraph(f"{marker} {text}", s)]
def note(text):
return [Paragraph(f"<b>Note:</b> {text}", NOTE)]
def warn(text):
return [Paragraph(f"<b>Caution:</b> {text}", WARN)]
def tip(text):
return [Paragraph(f"<b>Tip:</b> {text}", TIP)]
def hr(color=TEAL, thickness=0.8):
return [HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=6, spaceBefore=2)]
def spacer(h=6):
return [Spacer(1, h)]
def tbl_style(header_color=NAVY, stripe=GREY_BG):
return TableStyle([
("BACKGROUND", (0,0), (-1,0), header_color),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
("ALIGN", (0,0), (-1,0), "CENTER"),
("VALIGN", (0,0), (-1,-1),"MIDDLE"),
("FONTNAME", (0,1), (-1,-1),"Helvetica"),
("FONTSIZE", (0,1), (-1,-1), 8.5),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, stripe]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#CBD5E1")),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("ROUNDEDCORNERS", [3]),
])
def p(t, sty=TABLE_CELL):
return Paragraph(t, sty)
def pc(t):
return Paragraph(t, TABLE_CELL_C)
# ─── Cover Page ─────────────────────────────────────────────────────────────
def cover_page():
story = []
# Blue banner block using table trick
cover_data = [[Paragraph("""
<font size="28" color="white"><b>Pacemaker Programming<br/>
& Troubleshooting</b></font>
""", style("ct", fontSize=28, textColor=WHITE, fontName="Helvetica-Bold",
leading=36, alignment=TA_CENTER, spaceAfter=10))],
[Paragraph("Comprehensive Study Guide", style("cs", fontSize=16,
textColor=HexColor("#BAE6FD"), fontName="Helvetica",
alignment=TA_CENTER, leading=22))],
[Paragraph("Cardiology | Electrophysiology | Emergency Medicine", style("ctg",
fontSize=11, textColor=HexColor("#FDE68A"), fontName="Helvetica-Oblique",
alignment=TA_CENTER, leading=16))]
]
cover_tbl = Table(cover_data, colWidths=[CONTENT_W])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING",(0,0), (-1,-1), 18),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
("ROUNDEDCORNERS", [6]),
]))
story.append(Spacer(1, 30))
story.append(cover_tbl)
story.append(Spacer(1, 20))
# Topics covered
topics_data = [
[Paragraph("<b>Topics Covered in This Guide</b>", style("tch", fontSize=11,
textColor=NAVY, fontName="Helvetica-Bold", alignment=TA_CENTER))]
]
topics_tbl = Table(topics_data, colWidths=[CONTENT_W])
topics_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLU),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 8),
]))
story.append(topics_tbl)
story.append(Spacer(1, 8))
topic_items = [
("1", "NBG Pacemaker Code & Nomenclature"),
("2", "Pacemaker Components & Lead Systems"),
("3", "Common Pacing Modes – VVI, DDD, AAI, VVIR, DDDR"),
("4", "Pacemaker Programming Parameters"),
("5", "Advanced Features – CRT, Rate Modulation, Hysteresis"),
("6", "Indications for Permanent Pacing (Class I/II)"),
("7", "Pacemaker Malfunction – Failure to Capture, Sense, Rate"),
("8", "Troubleshooting Algorithm & ECG Analysis"),
("9", "Pacemaker-Mediated Tachycardia (PMT)"),
("10", "Magnet Application & Perioperative Management"),
("11", "High-Yield Tables, Mnemonics & Quick-Reference"),
]
rows = [[Paragraph(f"<b>{n}.</b> {t}", BODY)] for n, t in topic_items]
tbl = Table(rows, colWidths=[CONTENT_W])
tbl.setStyle(TableStyle([
("ROWBACKGROUNDS", (0,0), (-1,-1), [WHITE, GREY_BG]),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("GRID", (0,0), (-1,-1), 0.3, HexColor("#CBD5E1")),
]))
story.append(tbl)
story.append(Spacer(1, 20))
story.append(Paragraph(
"Sources: ROSEN's Emergency Medicine (9e) · Braunwald's Heart Disease (12e) · "
"Roberts & Hedges' Clinical Procedures in Emergency Medicine · Miller's Anesthesia (10e)",
style("src", fontSize=8, textColor=GREY_TXT, fontName="Helvetica-Oblique",
alignment=TA_CENTER, leading=12)
))
story.append(PageBreak())
return story
# ─── Section 1: NBG Code ─────────────────────────────────────────────────────
def section_nbg():
story = []
story += h1("SECTION 1: The NBG Pacemaker Code")
story += para(
"The <b>North American Society of Pacing and Electrophysiology / British Pacing and "
"Electrophysiology Group (NBG) code</b>, first established in 1974 and periodically "
"revised, provides a standardized 5-letter nomenclature for all cardiac pacing devices. "
"In daily clinical use, only the first three letters are quoted (e.g., VVI, DDD).")
story += spacer(8)
story += h2("Five-Position NBG Code")
nbg_data = [
[pc("Position"), pc("I"), pc("II"), pc("III"), pc("IV"), pc("V")],
[p("<b>Meaning</b>"), p("Chamber\nPaced"), p("Chamber\nSensed"),
p("Response\nto Sensing"), p("Rate\nModulation"), p("Antitachy\nFunction")],
[p("<b>Options</b>"),
p("O – None\nA – Atrium\nV – Ventricle\nD – Dual (A+V)"),
p("O – None\nA – Atrium\nV – Ventricle\nD – Dual (A+V)"),
p("O – None\nT – Triggered\nI – Inhibited\nD – Dual (T+I)"),
p("O – None\nR – Rate modulation\nM – Multiprogrammable\nC – Communicating"),
p("O – None\nP – Antitachy pacing\nS – Shock\nD – Dual (P+S)")],
]
nbg_tbl = Table(nbg_data, colWidths=[CONTENT_W/6.3]*6)
nbg_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#CBD5E1")),
("BACKGROUND", (0,1), (0,-1), LIGHT_BLU),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("ROWBACKGROUNDS",(1,2), (-1,-1), [WHITE, GREY_BG]),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
]))
story.append(nbg_tbl)
story += spacer(10)
story += note("Positions IV and V are omitted in everyday conversation. Most reports use three letters only (e.g., 'the patient is in DDD').")
story += spacer(8)
story += h2("Mnemonic: CSRR-A")
story.append(Paragraph(
"<b>C</b>hamber paced · <b>S</b>ensed chamber · <b>R</b>esponse to sensing · "
"<b>R</b>ate modulation · <b>A</b>ntitachycardia",
style("mn", fontSize=11, textColor=NAVY, fontName="Helvetica-Bold",
alignment=TA_CENTER, backColor=LIGHT_BLU, leading=18,
borderPad=8, spaceAfter=10)
))
story += h2("Key Pacing Modes – Explained")
modes_data = [
[pc("Mode"), pc("Full Meaning"), pc("Paces"), pc("Senses"), pc("Behavior"), pc("Typical Use")],
[pc("<b>VOO</b>"), p("Ventricle paced, no sensing, no response"),
pc("V"), pc("None"), p("Fixed-rate asynchronous; ignores intrinsic beats"),
p("Magnet mode; EMI; perioperative")],
[pc("<b>AOO</b>"), p("Atrium paced, no sensing, no response"),
pc("A"), pc("None"), p("Fixed-rate atrial asynchronous"),
p("Magnet mode, atrium only")],
[pc("<b>VVI</b>"), p("Ventricle paced, Ventricle sensed, Inhibited"),
pc("V"), pc("V"), p("Paces V if no intrinsic beat; inhibited by native QRS"),
p("AF + bradycardia; simplest demand mode")],
[pc("<b>AAI</b>"), p("Atrium paced, Atrium sensed, Inhibited"),
pc("A"), pc("A"), p("Paces A if no intrinsic P; inhibited by native P"),
p("SSS with intact AV conduction")],
[pc("<b>DDD</b>"), p("Dual paced, Dual sensed, Dual response"),
pc("A+V"), pc("A+V"), p("Tracks atrial rate to pace ventricle; inhibited by intrinsic activity"),
p("Most physiologic; gold standard")],
[pc("<b>VDD</b>"), p("Ventricle paced, Dual sensed, Dual response"),
pc("V"), pc("A+V"), p("Senses atrium, paces ventricle only; maintains AV sync"),
p("Normal SA node, AV block")],
[pc("<b>DDI</b>"), p("Dual paced, Dual sensed, Inhibited"),
pc("A+V"), pc("A+V"), p("No P-wave tracking; prevents atrial tachycardia tracking"),
p("Paroxysmal AF with brady")],
[pc("<b>VVIR</b>"), p("VVI + Rate modulation"),
pc("V"), pc("V"), p("VVI with sensor-driven rate increase on activity"),
p("Active patients, chronotropic incompetence")],
[pc("<b>DDDR</b>"), p("DDD + Rate modulation"),
pc("A+V"), pc("A+V"), p("DDD with sensor-driven upper rate limit"),
p("Optimal for most patients")],
]
modes_tbl = Table(modes_data, colWidths=[1.4*cm, 3.6*cm, 1.0*cm, 1.0*cm, 4.2*cm, 3.5*cm])
modes_tbl.setStyle(tbl_style(NAVY, GREY_BG))
story.append(modes_tbl)
story += spacer(8)
story += tip("DDD is the default mode for most dual-chamber devices. It provides AV synchrony, rate response, and both sensing chambers – the most physiologic option available.")
return story
# ─── Section 2: Components ───────────────────────────────────────────────────
def section_components():
story = []
story += h1("SECTION 2: Pacemaker Components & Lead Systems")
story += h2("Pulse Generator")
comp_data = [
[pc("<b>Component</b>"), pc("<b>Detail</b>")],
[p("Casing"), p("Hermetically sealed titanium or metal; ~30 g")],
[p("Battery"), p("Lithium-iodine cell; lasts 7-12 years (4-10+ years depending on usage)")],
[p("Battery discharge"), p("Gradual decline – no sudden failure; rate drop is the earliest sign of depletion")],
[p("Microprocessor"), p("Semiconductor chip; controls timing, sensing, telemetry")],
[p("Reed switch"), p("Closed by external magnet; converts to asynchronous (fixed-rate) pacing")],
[p("Telemetry"), p("Allows radiotelemetric reprogramming post-implantation – no surgery needed")],
[p("Typical weight"), p("~30–50 g; newer devices thinner and lighter")],
]
comp_tbl = Table(comp_data, colWidths=[4*cm, CONTENT_W-4*cm])
comp_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(comp_tbl)
story += spacer(10)
story += h2("Lead Systems")
story += h3("Lead Configurations")
leads_data = [
[pc("<b>Type</b>"), pc("<b>Electrodes</b>"), pc("<b>Advantages</b>"), pc("<b>Disadvantages</b>")],
[p("<b>Unipolar</b>"),
p("Cathode: lead tip in heart\nAnode: pulse generator casing"),
p("Larger pacing spike on ECG (easier to see)"),
p("Prone to oversensing (myopotentials, EMI); not compatible with ICD")],
[p("<b>Bipolar</b>"),
p("Both electrodes in heart, ~2 cm apart (tip cathode, ring anode)"),
p("Less EMI; compatible with ICD; preferred in modern devices"),
p("Thicker lead; draws more current")],
]
leads_tbl = Table(leads_data, colWidths=[2.2*cm, 3.5*cm, 4.0*cm, 4.0*cm])
leads_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(leads_tbl)
story += spacer(8)
story += h3("Lead Placement by Device Type")
place_data = [
[pc("<b>Device</b>"), pc("<b>Lead Positions</b>"), pc("<b>Access Route</b>"), pc("<b>Indication</b>")],
[p("Single-chamber (VVI)"), p("RV apex"), p("Subclavian / cephalic vein"), p("AF + bradycardia")],
[p("Single-chamber (AAI)"), p("RA appendage"), p("Subclavian / cephalic vein"), p("SSS + intact AV node")],
[p("Dual-chamber (DDD)"), p("RA + RV"), p("Subclavian / cephalic vein"), p("AV block; most patients")],
[p("Biventricular (CRT)"), p("RA + RV + LV (via coronary sinus)"), p("Subclavian / cephalic vein"), p("HFrEF + LBBB + QRS ≥150 ms")],
[p("Leadless pacemaker"), p("Self-contained in RV"), p("Femoral vein (transcatheter)"), p("Infection risk; no pocket needed")],
[p("Epicardial lead"), p("External epicardium"), p("Open surgery"), p("Post-cardiac surgery (temporary)")],
]
place_tbl = Table(place_data, colWidths=[3.3*cm, 3.8*cm, 3.5*cm, 3.1*cm])
place_tbl.setStyle(tbl_style(NAVY, GREY_BG))
story.append(place_tbl)
story += spacer(8)
story += note(
"The pacing electrical stimulus is a triphasic wave: intrinsic deflection + far-field potential "
"+ injury current. Typical parameters: 0.1–20 mA, 2 ms duration, ~15 V. "
"The pacemaker is programmed to pace at 60–80 beats/min by default.")
return story
# ─── Section 3: Programming Parameters ──────────────────────────────────────
def section_programming():
story = []
story += h1("SECTION 3: Pacemaker Programming Parameters")
story += para(
"Modern pacemakers are fully programmable via telemetry wand. Key parameters "
"include rate settings, output, sensitivity, timing intervals, and rate-response settings. "
"Understanding each parameter is essential for optimizing pacing and troubleshooting.")
story += h2("Core Programmable Parameters")
params_data = [
[pc("<b>Parameter</b>"), pc("<b>Definition</b>"), pc("<b>Typical Value</b>"), pc("<b>Clinical Notes</b>")],
[p("<b>Base Rate (LRL)</b>"),
p("Lower rate limit – minimum pacing rate regardless of activity"),
p("60–80 bpm"), p("Increase if patient symptomatic at lower rates")],
[p("<b>Upper Rate Limit (URL)</b>"),
p("Maximum tracking rate in DDD/VDD; prevents rapid ventricular response"),
p("120–180 bpm"), p("Important in atrial tachyarrhythmias")],
[p("<b>AV Delay (AVD)</b>"),
p("Time from atrial pacing/sensing to ventricular pacing; simulates PR interval"),
p("120–200 ms"), p("Prolonged AV delay maximizes native ventricular conduction")],
[p("<b>Output (Amplitude)</b>"),
p("Voltage (V) or current (mA) of pacing pulse"),
p("2.5–5.0 V; 0.5 ms pulse width"), p("Set at 2–3x the capture threshold for safety margin")],
[p("<b>Pulse Width</b>"),
p("Duration of the pacing stimulus"),
p("0.4–0.5 ms"), p("Longer pulse width = lower capture threshold; uses more battery")],
[p("<b>Sensitivity</b>"),
p("Minimum intracardiac signal amplitude that triggers sensing (mV)"),
p("Atrium: 0.5 mV\nVentricle: 2–3 mV"), p("Lower value = more sensitive (detects smaller signals)")],
[p("<b>Refractory Period</b>"),
p("Time after a paced/sensed event during which sensing is disabled"),
p("A: 200–300 ms\nV: 250–400 ms"), p("Prevents T-wave oversensing and double-counting")],
[p("<b>PVARP</b>"),
p("Post-Ventricular Atrial Refractory Period – atrial refractory after ventricular event"),
p("250–400 ms"), p("Prevents tracking of retrograde P waves (prevents PMT)")],
[p("<b>Hysteresis</b>"),
p("Pacing triggered at rate above the escape rate, allowing native rhythm dominance"),
p("Escape rate 50 bpm\nPacing rate 70 bpm"), p("Preserves intrinsic conduction; reduces unnecessary pacing")],
]
params_tbl = Table(params_data, colWidths=[3.2*cm, 4.5*cm, 2.5*cm, 3.5*cm])
params_tbl.setStyle(tbl_style(NAVY, GREY_BG))
story.append(params_tbl)
story += spacer(10)
story += h2("Rate-Modulation (Rate-Responsive Pacing)")
story += para(
"The <b>'R'</b> designation (Position IV of NBG code) indicates rate-responsive pacing. "
"Sensors detect physiologic demand and increase the pacing rate automatically:")
sensors_data = [
[pc("<b>Sensor Type</b>"), pc("<b>Detects</b>"), pc("<b>Response</b>"), pc("<b>Limitation</b>")],
[p("Accelerometer / Piezoelectric"), p("Body movement / vibration"), p("Fastest response to activity"), p("Responds to non-exercise vibration (riding)")],
[p("Minute Ventilation"), p("Respiratory rate × tidal volume"), p("Reflects true metabolic demand"), p("Requires additional sensing; can malfunction with EMI")],
[p("QT Interval"), p("Catecholamine-driven QT shortening"), p("Good for emotional stress"), p("Affected by drugs, electrolytes")],
[p("Temperature sensor"), p("Core body temperature rise"), p("Accurate metabolic proxy"), p("Slow response to onset of exercise")],
[p("Venous O2 saturation"), p("Mixed venous O2 (SvO2 drop)"), p("True metabolic demand"), p("Requires additional lead")],
]
sensors_tbl = Table(sensors_data, colWidths=[3.8*cm, 3.8*cm, 3.3*cm, 2.8*cm])
sensors_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(sensors_tbl)
story += spacer(8)
story += h2("AV Delay Optimization")
story += para(
"An <b>excessively short AV delay</b> causes ventricular pacing before atrial contraction "
"completes, reducing preload (mimics pacemaker syndrome). "
"An <b>excessively long AV delay</b> allows diastolic mitral regurgitation. "
"Optimal AV delay (typically 120–200 ms sensed, 150–200 ms paced) is determined by:")
story += bullet("Echocardiographic Doppler assessment of mitral E and A wave separation")
story += bullet("Maximizing stroke volume / cardiac output")
story += bullet("Minimizing pacemaker syndrome symptoms")
story += spacer(8)
story += tip(
"Sensed AV delay is typically programmed 30–50 ms shorter than paced AV delay "
"because native P-wave conduction has already started when sensed.")
return story
# ─── Section 4: Indications ─────────────────────────────────────────────────
def section_indications():
story = []
story += h1("SECTION 4: Indications for Permanent Pacing")
story += h2("Class I Indications (ACC/AHA)")
ci_data = [
[pc("#"), pc("Indication")],
[pc("1"), p("Symptomatic sinus node dysfunction (SSS) directly attributable to SND")],
[pc("2"), p("Symptomatic SND or AV block secondary to guideline-directed therapy with no alternative")],
[pc("3"), p("Permanent AF with symptomatic bradycardia")],
[pc("4"), p("Symptomatic AV block from a known reversible cause (Lyme disease, drug toxicity) without resolution")],
[pc("5"), p("Acquired 2nd-degree Mobitz II AV block, high-grade AV block, or 3rd-degree (complete) AV block – regardless of symptoms")],
[pc("6"), p("Neuromuscular disease (muscular dystrophy, Kearns-Sayre) with 2nd/3rd-degree AV block + survival >1 year")],
[pc("7"), p("Syncope + bundle branch block with HV interval >70 ms or infra-nodal block on EPS")],
[pc("8"), p("Alternating bundle branch block")],
[pc("9"), p("Post-operative SND or AV block with persistent symptoms/hemodynamic instability after cardiac surgery")],
[pc("10"), p("Transcatheter aortic valve replacement (TAVR) with new persistent 3rd-degree or Mobitz II AV block")],
[pc("11"), p("Post-MI with Mobitz II, high-grade AV block, 3rd-degree block, or alternating BBB (after waiting period)")],
]
ci_tbl = Table(ci_data, colWidths=[1.0*cm, CONTENT_W-1.0*cm])
ci_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), GREEN),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ALIGN", (0,0), (0,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, GREY_BG]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#CBD5E1")),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
]))
story.append(ci_tbl)
story += spacer(10)
story += h2("Mode Selection by Clinical Scenario")
mode_ind_data = [
[pc("<b>Clinical Scenario</b>"), pc("<b>Recommended Mode</b>"), pc("<b>Rationale</b>")],
[p("Complete AV block + normal SA node"), p("DDD / DDDR"), p("Maintains AV synchrony; tracks sinus rate")],
[p("SSS alone + intact AV conduction"), p("AAI / AAIR"), p("Avoids unnecessary RV pacing")],
[p("AF (permanent) + bradycardia"), p("VVI / VVIR"), p("Atrial sensing irrelevant in AF")],
[p("HFrEF + LBBB + QRS ≥150 ms"), p("CRT-P (BiV) or CRT-D"), p("Resynchronizes ventricles; improves EF")],
[p("Vasovagal syncope (selected)"), p("DDI / DDD with rate-drop response"), p("Paces during cardioinhibitory vasovagal episode")],
[p("Chronotropic incompetence"), p("DDDR or VVIR"), p("Rate modulation needed for exercise")],
[p("Perioperative / temporary"), p("VOO (magnet) or external pacer"), p("Prevents inhibition by electrosurgery (EMI)")],
]
mode_ind_tbl = Table(mode_ind_data, colWidths=[4.5*cm, 3.5*cm, CONTENT_W-8.0*cm])
mode_ind_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(mode_ind_tbl)
return story
# ─── Section 5: Troubleshooting ─────────────────────────────────────────────
def section_troubleshooting():
story = []
story += h1("SECTION 5: Pacemaker Malfunction & Troubleshooting")
story += para(
"Pacemaker malfunction occurs in <b><5% of patients</b> after implantation and is "
"rarely life-threatening. Most malfunction is due to <b>inappropriate sensing</b> "
"(most common), followed by <b>failure to capture</b>. "
"ECG analysis is the first step in identifying the type of malfunction.")
story += h2("The Three Categories of Malfunction")
# ── 1. Failure to Capture
story += h3("1. Failure to Capture")
story += para(
"<b>Definition:</b> A pacing spike is present but NOT followed by a P wave (atrial) "
"or QRS complex (ventricular). May also present as complete absence of spikes.")
ftc_data = [
[pc("<b>ECG Finding</b>"), pc("<b>Possible Cause</b>"), pc("<b>Management</b>")],
[p("Spikes present, no complex follows"),
p("Lead displacement (most common)\nExit block\nLead fracture/insulation break"),
p("Increase output amplitude\nReposition lead\nReprogramme")],
[p("No spikes at all"),
p("Battery depletion\nLead disconnection from generator\nOversensing causing inhibition"),
p("Generator replacement\nCheck lead connections\nMagnet to assess capture")],
[p("Intermittent capture loss"),
p("Increased pacing threshold (post-MI, drugs, electrolytes)\nFibrosis at lead tip"),
p("Increase output\nOptimise electrolytes (K+, Mg2+)\nSteroid-eluting lead if available")],
]
ftc_tbl = Table(ftc_data, colWidths=[3.8*cm, 4.8*cm, 5.1*cm])
ftc_tbl.setStyle(tbl_style(RED, HexColor("#FEF2F2")))
story.append(ftc_tbl)
story += spacer(6)
# ── 2. Failure to Sense
story += h3("2. Failure to Sense (Undersensing)")
story += para(
"<b>Definition:</b> The pacemaker fails to detect intrinsic cardiac activity and fires "
"inappropriately (competitive pacing). On ECG: pacing spikes appear during or after "
"intrinsic P waves or QRS complexes.")
fts_data = [
[pc("<b>Cause</b>"), pc("<b>Mechanism</b>"), pc("<b>Management</b>")],
[p("Lead displacement"), p("Electrode not in contact with endocardium; low amplitude signal sensed"),
p("Reposition lead")],
[p("Low-amplitude intracardiac signal"), p("Small native P or QRS waves below sensitivity threshold"),
p("Increase sensitivity (lower mV threshold)")],
[p("Lead fracture / insulation break"), p("Partial signal loss along conductor"),
p("Replace lead")],
[p("Fibrosis / maturation"), p("Signal amplitude decreases after initial implant healing period (weeks 2–8)"),
p("Reprogramme sensitivity; may require lead revision")],
[p("New myocardial infarction"), p("Reduced electrogram amplitude at lead tip"),
p("Increase sensitivity; reposition")],
]
fts_tbl = Table(fts_data, colWidths=[3.5*cm, 5.0*cm, 5.2*cm])
fts_tbl.setStyle(tbl_style(ORANGE, HexColor("#FFF7ED")))
story.append(fts_tbl)
story += spacer(6)
# ── 3. Oversensing
story += h3("3. Oversensing (Inappropriate Inhibition)")
story += para(
"<b>Definition:</b> The pacemaker detects a non-cardiac or non-relevant signal and "
"incorrectly inhibits pacing. On ECG: long pauses in a pacemaker-dependent patient; "
"under-pacing relative to set rate.")
os_data = [
[pc("<b>Source of Interference</b>"), pc("<b>Type</b>"), pc("<b>Management</b>")],
[p("Myopotentials (skeletal muscle)"),
p("Particularly with unipolar leads and arm movements"),
p("Switch to bipolar; decrease sensitivity (increase mV threshold)")],
[p("T-wave sensing"),
p("T-wave amplitude exceeds sensing threshold; counts as a second QRS"),
p("Shorten ventricular refractory period or increase sensitivity threshold")],
[p("Electromagnetic interference (EMI)"),
p("Electrosurgery (most common in-hospital), MRI, diathermy, TENS units"),
p("Apply magnet (VOO); reprogram; use bipolar electrosurgery")],
[p("P-wave far-field sensing"),
p("Ventricular channel inappropriately senses large P waves"),
p("Increase ventricular sensitivity threshold; PVARP extension")],
[p("Cross-talk (dual-chamber)"),
p("Ventricular channel senses atrial pacing output"),
p("Ventricular blanking period adjustment; reduce atrial output")],
]
os_tbl = Table(os_data, colWidths=[4.0*cm, 4.5*cm, 5.2*cm])
os_tbl.setStyle(tbl_style(HexColor("#7C3AED"), HexColor("#F5F3FF")))
story.append(os_tbl)
story += spacer(8)
# ── 4. Inappropriate Rate
story += h3("4. Inappropriate Pacemaker Rate")
rate_data = [
[pc("<b>Rate Problem</b>"), pc("<b>Cause</b>"), pc("<b>Management</b>")],
[p("<b>Slower than programmed</b>"),
p("Battery depletion (most common)\nRate-drop algorithm triggered\nMagnet applied"),
p("Generator replacement if battery depleted\nCheck magnet application")],
[p("<b>Faster than programmed</b>"),
p("Pacemaker-mediated tachycardia (PMT)\nTracking atrial dysrhythmia (AF/flutter) in DDD\nRunaway pacemaker (rare – circuit failure)"),
p("Extend PVARP\nMode switch programming\nEmergency: magnet application")],
[p("<b>Rate at URL (upper rate limit)</b>"),
p("2:1 AV block behavior: device paces at half the atrial rate (Wenckebach behavior)"),
p("Increase URL; AV delay optimization")],
]
rate_tbl = Table(rate_data, colWidths=[3.5*cm, 5.5*cm, 4.7*cm])
rate_tbl.setStyle(tbl_style(NAVY, GREY_BG))
story.append(rate_tbl)
return story
# ─── Section 6: PMT & Special Situations ─────────────────────────────────────
def section_pmt():
story = []
story += h1("SECTION 6: Pacemaker-Mediated Tachycardia & Special Situations")
story += h2("Pacemaker-Mediated Tachycardia (PMT)")
story += para(
"PMT is a re-entry tachycardia unique to dual-chamber pacemakers (DDD/VDD). "
"It is also called <b>endless-loop tachycardia</b>.")
pmt_steps = [
("Trigger", "A premature ventricular contraction (PVC) or loss of AV synchrony generates a retrograde P-wave (retrograde VA conduction)."),
("Detection", "The retrograde P-wave falls outside the PVARP and is sensed by the atrial channel as a new atrial event."),
("Tracking", "The pacemaker then triggers a ventricular paced beat after the programmed AV delay."),
("Loop", "This ventricular beat again conducts retrogradely, creating another retrograde P-wave... and so on."),
("Rate", "The loop sustains at or near the upper rate limit (URL) – typically 100-180 bpm."),
]
pmt_data = [[pc("<b>Step</b>"), pc("<b>Event</b>"), pc("<b>Detail</b>")]]
for s, d in pmt_steps:
pmt_data.append([pc(f"<b>{s}</b>"), p(""), p(d)])
# Simplify:
pmt_data2 = [[pc("<b>Step</b>"), pc("<b>Detail</b>")]]
for s, d in pmt_steps:
pmt_data2.append([p(f"<b>{s}</b>"), p(d)])
pmt_tbl = Table(pmt_data2, colWidths=[2.5*cm, CONTENT_W-2.5*cm])
pmt_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), RED),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [HexColor("#FEF2F2"), WHITE]),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#CBD5E1")),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(pmt_tbl)
story += spacer(6)
story += h3("PMT Termination & Prevention")
story += bullet("<b>Acute termination:</b> Apply a pacemaker magnet – converts to VOO/asynchronous mode, breaking the re-entry loop")
story += bullet("<b>Prevention:</b> Lengthen PVARP (post-ventricular atrial refractory period) – retrograde P-wave falls within refractory period")
story += bullet("<b>PMT algorithm:</b> Modern devices detect sustained upper-rate pacing and automatically extend PVARP for one cycle to break the loop")
story += bullet("<b>Reduce VA conduction:</b> Optimize AV delay; consider ablation of VA conduction in refractory cases")
story += spacer(8)
story += h2("Mode Switch")
story += para(
"In DDD pacemakers, <b>automatic mode switch (AMS)</b> is a protective algorithm that "
"temporarily switches the device from a tracking mode (DDD) to a non-tracking mode (DDI or VVI) "
"when a rapid atrial arrhythmia (AF, flutter) is detected. This prevents ventricular pacing "
"at the upper rate limit in response to rapid atrial activity. The device returns to DDD "
"when the atrial arrhythmia terminates.")
story += spacer(8)
story += h2("Magnet Application – Key Rules")
mag_data = [
[pc("<b>Action</b>"), pc("<b>Effect</b>"), pc("<b>Clinical Use</b>")],
[p("Magnet placed over generator"),
p("Closes reed switch → disables sensing → asynchronous (VOO/AOO/DOO) fixed-rate pacing"),
p("Assess capture; prevent inhibition during electrosurgery; break PMT")],
[p("Magnet rate"),
p("Usually same as programmed rate, but each manufacturer varies. ~85 bpm common for Medtronic at normal battery"),
p("Verify manufacturer default; rate drop may indicate battery depletion")],
[p("ICD + magnet"),
p("Suspends tachyarrhythmia therapies (shock/ATP) but does NOT necessarily alter pacing mode"),
p("Prevent inappropriate shocks during EMI; remove promptly")],
]
mag_tbl = Table(mag_data, colWidths=[3.5*cm, 5.5*cm, 4.7*cm])
mag_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(mag_tbl)
story += spacer(6)
story += warn(
"Magnet behavior varies by manufacturer and device programming. Always confirm with "
"manufacturer specifications or device interrogation. Magnet does NOT terminate PMT in ICD devices "
"the same way it does in pure pacemakers.")
story += spacer(8)
story += h2("Perioperative Pacemaker Management")
story += bullet("Assess pacemaker dependency before surgery – is patient pacemaker-dependent?")
story += bullet("Mode: reprogram to asynchronous (VOO) mode OR have magnet available if electrosurgery planned")
story += bullet("Use <b>bipolar electrosurgery</b> whenever possible to reduce EMI")
story += bullet("Grounding pad placed as far as possible from the pulse generator")
story += bullet("Post-operative device interrogation recommended after any significant EMI exposure")
story += bullet("MRI: confirm device is <b>MRI-conditional</b> and follow institutional protocol")
return story
# ─── Section 7: Troubleshooting Algorithm ────────────────────────────────────
def section_algorithm():
story = []
story += h1("SECTION 7: ECG-Based Troubleshooting Algorithm")
story += para(
"When a patient with a pacemaker presents with symptoms (syncope, pre-syncope, "
"palpitations, shortness of breath), use the following systematic ECG approach:")
algo_data = [
[Paragraph("<b>Step 1</b>", TABLE_CELL_C),
Paragraph("Are pacemaker spikes present on the ECG?", TABLE_CELL)],
[Paragraph("<b>Yes</b>", style("y", fontSize=8.5, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Proceed to Step 2 (spike present but no capture → failure to capture)", TABLE_CELL)],
[Paragraph("<b>No</b>", style("n", fontSize=8.5, textColor=RED, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Is patient's native rate above the programmed rate? → Appropriate inhibition. OR: Is rate below programmed? → Battery depletion / oversensing / lead problem", TABLE_CELL)],
[Paragraph("<b>Step 2</b>", TABLE_CELL_C),
Paragraph("Is each spike followed by a P wave (atrial) or QRS (ventricular)?", TABLE_CELL)],
[Paragraph("<b>Yes</b>", style("y2", fontSize=8.5, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Capture is intact. Proceed to evaluate rate and AV timing.", TABLE_CELL)],
[Paragraph("<b>No</b>", style("n2", fontSize=8.5, textColor=RED, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Failure to capture → Check lead integrity, threshold, battery, electrolytes. Apply magnet if needed.", TABLE_CELL)],
[Paragraph("<b>Step 3</b>", TABLE_CELL_C),
Paragraph("Is the pacemaker firing when it should be inhibited (i.e., during intrinsic beats)?", TABLE_CELL)],
[Paragraph("<b>Yes</b>", style("y3", fontSize=8.5, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Undersensing → Lead displacement, low electrogram amplitude, increased sensitivity threshold needed.", TABLE_CELL)],
[Paragraph("<b>No</b>", style("n3", fontSize=8.5, textColor=RED, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Sensing appears intact.", TABLE_CELL)],
[Paragraph("<b>Step 4</b>", TABLE_CELL_C),
Paragraph("Is the pacemaker NOT firing when it should (pauses, heart rate below programmed LRL)?", TABLE_CELL)],
[Paragraph("<b>Yes</b>", style("y4", fontSize=8.5, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Oversensing → Check for myopotentials, T-wave sensing, EMI. Apply magnet to break oversensing temporarily.", TABLE_CELL)],
[Paragraph("<b>Step 5</b>", TABLE_CELL_C),
Paragraph("Is the ventricular rate faster than expected (at or near URL)?", TABLE_CELL)],
[Paragraph("<b>Yes</b>", style("y5", fontSize=8.5, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("Consider PMT (apply magnet), atrial arrhythmia tracking (check for mode switch), or runaway pacemaker (rare).", TABLE_CELL)],
]
algo_tbl = Table(algo_data, colWidths=[1.8*cm, CONTENT_W-1.8*cm])
algo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), LIGHT_BLU),
("FONTNAME", (0,0), (0,-1), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("GRID", (0,0), (-1,-1), 0.4, HexColor("#CBD5E1")),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("ROWBACKGROUNDS",(0,0),(-1,-1),[WHITE, GREY_BG]),
]))
story.append(algo_tbl)
story += spacer(8)
story += note(
"Always correlate ECG findings with patient symptoms and check programmed parameters via "
"device interrogation (telemetry wand). The device's stored electrograms are invaluable "
"for diagnosing intermittent malfunction.")
return story
# ─── Section 8: Quick Reference & High-Yield Tables ─────────────────────────
def section_quickref():
story = []
story += h1("SECTION 8: High-Yield Quick Reference")
story += h2("Malfunction Summary Table")
sum_data = [
[pc("<b>Malfunction</b>"), pc("<b>ECG Finding</b>"), pc("<b>Most Common Cause</b>"), pc("<b>First-Line Action</b>")],
[p("<b>Failure to Capture</b>"), p("Spike without P/QRS"), p("Lead displacement"), p("Increase output; check lead")],
[p("<b>Undersensing</b>"), p("Spikes during native beats"), p("Lead displacement"), p("Increase sensitivity (↓ mV threshold)")],
[p("<b>Oversensing</b>"), p("Long pauses; rate < LRL"), p("Myopotentials / EMI"), p("Magnet; decrease sensitivity (↑ mV)")],
[p("<b>PMT</b>"), p("Sustained tachycardia at URL"), p("Retrograde VA conduction"), p("Magnet; extend PVARP")],
[p("<b>Battery depletion</b>"), p("Gradual rate slowing"), p("End of battery life (>5-7 yr)"), p("Generator replacement")],
[p("<b>Lead fracture</b>"), p("Intermittent failure; noise"), p("Trauma, subclavian crush"), p("Lead replacement")],
[p("<b>Pacemaker syndrome</b>"), p("VA dissociation in VVI"), p("VVI in intact VA conduction"), p("Upgrade to dual-chamber")],
]
sum_tbl = Table(sum_data, colWidths=[3.5*cm, 3.5*cm, 3.8*cm, 3.0*cm])
sum_tbl.setStyle(tbl_style(NAVY, GREY_BG))
story.append(sum_tbl)
story += spacer(10)
story += h2("Threshold Parameters – Normal vs Abnormal")
thr_data = [
[pc("<b>Parameter</b>"), pc("<b>Normal / Acceptable</b>"), pc("<b>Alarm Value</b>")],
[p("Pacing threshold (ventricle)"), p("≤1.0 V at 0.5 ms at implant"), p(">2.0 V at implant; rising post-implant")],
[p("Sensing – ventricular R-wave"), p(">5 mV"), p("<4 mV – risk of undersensing")],
[p("Sensing – atrial P-wave"), p(">2 mV"), p("<1.5 mV")],
[p("Lead impedance"), p("300–1000 Ω (endovascular)"), p("<200 Ω (insulation break); >2000 Ω (fracture/disconnection)")],
[p("Battery voltage"), p(">2.8 V = adequate"), p("<2.4 V = end-of-life indicator")],
[p("Pacing rate"), p("60–80 bpm (programmed)"), p(">100 bpm at rest or <55 bpm at programmed 60")],
]
thr_tbl = Table(thr_data, colWidths=[3.8*cm, 4.5*cm, 5.4*cm])
thr_tbl.setStyle(tbl_style(TEAL, GREY_BG))
story.append(thr_tbl)
story += spacer(10)
story += h2("Drugs That Affect Pacing Thresholds")
drug_data = [
[pc("<b>Drug / Factor</b>"), pc("<b>Effect on Threshold</b>"), pc("<b>Clinical Note</b>")],
[p("Hyperkalemia"), p("Increases capture threshold"), p("Dialysis patients; may cause exit block")],
[p("Hypokalemia / Hypomagnesemia"), p("Increases capture threshold + arrhythmia risk"), p("Correct electrolytes before programming changes")],
[p("Flecainide / Propafenone"), p("Increases capture threshold"), p("May cause exit block; increase output")],
[p("Amiodarone"), p("Increases capture threshold (chronic)"), p("Particularly with long-term use")],
[p("Corticosteroids"), p("Decreases threshold"), p("Used in steroid-eluting leads to reduce fibrosis")],
[p("Hypothyroidism"), p("Increases threshold"), p("Treat underlying thyroid disease")],
[p("Hypoxia / Acidosis"), p("Increases threshold"), p("Optimize respiratory status")],
]
drug_tbl = Table(drug_data, colWidths=[3.8*cm, 3.8*cm, 6.1*cm])
drug_tbl.setStyle(tbl_style(ORANGE, HexColor("#FFF7ED")))
story.append(drug_tbl)
story += spacer(10)
story += h2("Pacemaker Syndrome")
story += para(
"<b>Definition:</b> Hemodynamic and symptomatic deterioration caused by <b>loss of AV synchrony</b>, "
"most commonly in VVI pacing with intact VA conduction.")
story += bullet("Symptoms: fatigue, dyspnea, palpitations, 'pounding' in neck/abdomen, near-syncope")
story += bullet("Signs: cannon A waves (JVP), variable S1, paradoxical splitting of S2, hypotension")
story += bullet("Treatment: upgrade to dual-chamber (DDD) pacing to restore AV synchrony")
story += spacer(8)
story += h2("Key Mnemonics")
mnemonics = [
("NBG Code – CSRRA",
"Chamber paced · Sensed chamber · Response to sensing · Rate modulation · Antitachycardia"),
("Failure to Capture Causes – BLADE",
"Battery depletion · Lead displacement · Altered threshold · Dislodgement · Electrolytes"),
("Oversensing Sources – MET",
"Myopotentials · Electromagnetic interference · T-wave sensing"),
("PMT Steps – TRDL",
"Trigger (PVC) · Retrograde P-wave · Detected by atrial channel · Loop established"),
]
for title, body in mnemonics:
mn_data = [[Paragraph(f"<b>{title}</b>", style("mnt", fontSize=9.5, textColor=NAVY,
fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph(body, style("mnb", fontSize=9, textColor=GREY_TXT,
fontName="Helvetica-Oblique", alignment=TA_LEFT, leading=13))]]
mn_tbl = Table(mn_data, colWidths=[4.5*cm, CONTENT_W-4.5*cm])
mn_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), LIGHT_BLU),
("BACKGROUND", (1,0), (-1,-1), WHITE),
("GRID", (0,0), (-1,-1), 0.5, TEAL),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING",(0,0), (-1,-1), 8),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0),(-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(mn_tbl)
story += spacer(4)
return story
# ─── Section 9: Practice Questions ───────────────────────────────────────────
def section_questions():
story = []
story += h1("SECTION 9: High-Yield Practice Questions")
questions = [
("Q1", "A patient with a VVI pacemaker presents with fatigue, dyspnea, and 'pounding in the neck.' "
"ECG shows VVI pacing with retrograde P waves. What is the diagnosis and treatment?",
"Pacemaker syndrome due to VA dissociation (loss of AV synchrony). Treat by upgrading to a dual-chamber "
"DDD pacemaker to restore AV synchrony."),
("Q2", "A pacemaker-dependent patient's ECG shows pacing spikes at the programmed rate, but each spike "
"is NOT followed by a QRS complex. What is the problem and what are the three most common causes?",
"Failure to capture. Most common causes: (1) lead displacement, (2) exit block / increased pacing "
"threshold, (3) battery depletion. First step: increase output voltage; apply magnet to assess capture."),
("Q3", "A DDD pacemaker patient presents with a regular tachycardia at 170 bpm. The ECG shows wide QRS "
"complexes at the programmed upper rate limit. There was a PVC just before onset. What is the diagnosis?",
"Pacemaker-mediated tachycardia (PMT / endless-loop tachycardia). The PVC caused retrograde VA conduction → "
"retrograde P-wave sensed outside PVARP → ventricular pacing → re-entry loop. "
"Terminate with magnet (VOO mode); prevent by extending PVARP."),
("Q4", "A patient's pacemaker fires at the programmed rate but fires during intrinsic QRS complexes "
"(competitive pacing seen on ECG). What type of malfunction is this and what is the fix?",
"Undersensing (failure to sense). The pacemaker is not detecting intrinsic beats. "
"Cause: lead displacement or low electrogram amplitude. Fix: increase sensitivity (decrease mV threshold); "
"reposition or replace lead if necessary."),
("Q5", "A patient with a DDDR pacemaker develops AF. What happens to pacemaker behavior? "
"What protective feature prevents rapid ventricular pacing?",
"In DDD mode, the pacemaker would track rapid atrial activity and pace the ventricle at the URL. "
"The protective feature is <b>Automatic Mode Switch (AMS)</b>: the device detects AF and switches to "
"DDI or VVI mode (non-tracking), pacing at the sensor-driven or base rate. It returns to DDD when AF terminates."),
("Q6", "List the five positions of the NBG pacemaker code and give an example for VVI and DDD.",
"I: Chamber paced (A/V/D/O) | II: Chamber sensed (A/V/D/O) | III: Response to sensing (I/T/D/O) | "
"IV: Rate modulation (R/M/C/O) | V: Antitachycardia function (P/S/D/O). "
"VVI = Ventricle paced, Ventricle sensed, Inhibited response. "
"DDD = Dual paced, Dual sensed, Dual (triggered + inhibited) response."),
("Q7", "What ECG finding differentiates unipolar from bipolar pacemaker leads?",
"Unipolar leads produce a <b>large pacing spike</b> (high amplitude, widely visible across all leads) "
"because the circuit spans from the heart to the pulse generator casing. "
"Bipolar leads produce a <b>small pacing spike</b> (may be barely visible) because both electrodes "
"are close together within the heart."),
("Q8", "A patient scheduled for laparoscopic surgery has a pacemaker. What preoperative steps are required?",
"(1) Identify device: manufacturer, model, programmed mode, dependency status. "
"(2) If pacemaker-dependent: reprogram to VOO or have pacemaker magnet available. "
"(3) Use bipolar electrosurgery whenever possible. "
"(4) Place grounding pad away from the generator and leads. "
"(5) Monitor for inhibition during procedure. "
"(6) Post-op device interrogation if significant EMI exposure."),
]
for qnum, question, answer in questions:
q_data = [
[Paragraph(f"<b>{qnum}</b>", style("qn", fontSize=9.5, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph(question, BODY)],
[Paragraph("A:", style("an", fontSize=9.5, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_CENTER, backColor=GREEN)),
Paragraph(answer, BODY)],
]
q_tbl = Table(q_data, colWidths=[1.0*cm, CONTENT_W-1.0*cm])
q_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), NAVY),
("BACKGROUND", (0,1), (0,1), GREEN),
("BACKGROUND", (1,0), (1,0), LIGHT_BLU),
("BACKGROUND", (1,1), (1,1), HexColor("#DCFCE7")),
("GRID", (0,0), (-1,-1), 0.5, HexColor("#CBD5E1")),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING",(0,0), (-1,-1), 6),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(q_tbl)
story += spacer(6)
return story
# ─── Page Number Canvas ───────────────────────────────────────────────────────
def add_page_number(canvas, doc):
canvas.saveState()
page_num = canvas.getPageNumber()
if page_num > 1: # Skip cover page
canvas.setFont("Helvetica", 8)
canvas.setFillColor(GREY_TXT)
canvas.drawCentredString(W/2, 1.2*cm,
f"Pacemaker Programming & Troubleshooting Study Guide | Page {page_num}")
canvas.setStrokeColor(TEAL)
canvas.setLineWidth(0.5)
canvas.line(1.8*cm, 1.5*cm, W-1.8*cm, 1.5*cm)
canvas.restoreState()
# ─── Assemble Document ────────────────────────────────────────────────────────
story = []
story += cover_page()
story += section_nbg()
story.append(PageBreak())
story += section_components()
story.append(PageBreak())
story += section_programming()
story.append(PageBreak())
story += section_indications()
story.append(PageBreak())
story += section_troubleshooting()
story.append(PageBreak())
story += section_pmt()
story.append(PageBreak())
story += section_algorithm()
story.append(PageBreak())
story += section_quickref()
story.append(PageBreak())
story += section_questions()
doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print(f"PDF generated: {OUTPUT}")
cd /tmp/workspace/pacemaker-study-guide && python3 generate_pdf.py 2>&1
python3 -c " from pypdf import PdfReader r = PdfReader('/tmp/workspace/pacemaker-study-guide/Pacemaker_Programming_Troubleshooting_Study_Guide.pdf') print(f'Pages: {len(r.pages)}') import os size = os.path.getsize('/tmp/workspace/pacemaker-study-guide/Pacemaker_Programming_Troubleshooting_Study_Guide.pdf') print(f'File size: {size/1024:.1f} KB') "
Pacemaker Programming Troubleshooting Study Guide
PDF Document · PDF
| Section | Content |
|---|---|
| 1 - NBG Code | Full 5-position code table, all pacing modes (VVI, AAI, DDD, VDD, DDI, VVIR, DDDR) with indications |
| 2 - Components | Pulse generator specs, unipolar vs bipolar leads, lead placement by device type (single/dual/CRT/leadless) |
| 3 - Programming Parameters | LRL, URL, AV delay, output, pulse width, sensitivity, refractory period, PVARP, hysteresis; rate-modulation sensors |
| 4 - Indications | All ACC/AHA Class I indications; mode selection by clinical scenario |
| 5 - Malfunction & Troubleshooting | Failure to capture, undersensing, oversensing, inappropriate rate - each with ECG findings, causes, and management tables |
| 6 - PMT & Special Situations | Endless-loop tachycardia mechanism, termination, automatic mode switch, magnet rules, perioperative management |
| 7 - Troubleshooting Algorithm | Step-by-step ECG-based decision table |
| 8 - Quick Reference | Master malfunction summary, threshold parameters, drugs affecting pacing threshold, pacemaker syndrome, mnemonics |
| 9 - Practice Questions | 8 high-yield Q&A covering all major exam topics |
Find recent pacemaker clinical guidelines and protocols
"cardiac pacing" AND "guidelines"
ACC AHA ESC pacemaker cardiac pacing guidelines 2024 2025
"cardiac pacing" AND "bradycardia" AND "guideline"
"conduction system pacing" AND "heart failure"
HRS 2023 cardiac physiologic pacing guideline conduction system pacing left bundle branch
PMID: 30412709
PMID: 37283271
PMID: 38382686
PMID: 36352513
PMID: 39268942
PMID: 39892565
PMID: 41968613
PMID: 39082698
| Organization | Acronym | Scope |
|---|---|---|
| American College of Cardiology / American Heart Association / Heart Rhythm Society | ACC/AHA/HRS | Bradycardia & conduction delay (foundational guideline) |
| Heart Rhythm Society + Asia-Pacific HRS + Latin American HRS | HRS/APHRS/LAHRS | Physiologic pacing, CRT, conduction system pacing |
| European Society of Cardiology | ESC/EHRA | European practice, syncope, EP consensus statements |
| Indication | Class | Level of Evidence |
|---|---|---|
| Symptomatic sinus node dysfunction | I | C |
| 3rd-degree or Mobitz II AV block (regardless of symptoms) | I | C |
| Symptomatic 2nd-degree AV block (any type) | I | B |
| AF with symptomatic bradycardia | I | C |
| Alternating BBB | I | C |
| HV interval >70 ms on EPS with syncope + BBB | I | B |
| Post-cardiac surgery persistent AV block | I | C |
| Biventricular pacing for HFrEF + LBBB + QRS ≥150 ms + LVEF ≤35% | I | A |
| Physiologic pacing (over RV apex pacing) when >40% ventricular pacing expected + LVEF 36-50% | IIa | B-R |
| Recommendation | Class | Evidence |
|---|---|---|
| CRT for HFrEF (LVEF ≤35%), LBBB, QRS ≥150 ms, NYHA II-III/ambulatory IV | I | A |
| CSP (HBP or LBBAP) as alternative to CRT when CRT is not feasible or fails | IIa | B |
| CSP preferred over RV pacing when pacing expected >40% and LVEF 36-50% | IIa | B |
| LBBAP as preferred CSP method (lower threshold, more reliable than HBP) | IIa | B |
| Upgrade from RV pacing to CSP or BiV for pacing-induced cardiomyopathy | IIa | B |
| AV node ablation + CSP for AF with symptomatic rapid ventricular response | IIa | B |
CSP vs. BiV pacing: CSP produced significantly greater QRS narrowing (-13.3 ms, p=0.02), improved NYHA class (p=0.02), and higher LVEF gain (+2.1%, p=0.03). No significant difference in lead threshold or procedure time.
Upgrade to CRT: LVEF improved +8.4% from baseline 35.5% (RCTs). Upgrade to LBBAP: LVEF improved +11.1% from 39.0%. NYHA class improved with all upgrade strategies. Complication rates: BiV upgrade ~3.7% infection over 24 months; CSP upgrade lead complications 1.8%.
CSP vs. BiV for PICM: CSP produced greater QRS shortening (-53.3 ms vs. -30.7 ms, p<0.001), higher response rate (84.7% vs. 67.6%), and fewer device-related complications (14.0% vs. 20.1%). HBP had greater QRS shortening; LBBAP had lower pacing thresholds.
HBP + AVNA for AF: LVEF improved +9.24%, NYHA class improved (-1.12). HBP had comparable efficacy to BiV pacing and LBBP for AF ablation, but lower success rate (85.97%) and more complications (16.1%) than LBBAP.
Rate-adaptive pacing (DDDR/VVIR) vs. fixed-rate: RAP-on improved peak VO2 (+1.35 mL/kg/min), exercise duration (+0.74 min), and peak HR (+19 bpm). However, benefit was much smaller in patients with HF (VO2 +0.36 vs. +1.95 in non-HF patients, non-significant in HF).
| Area | Status |
|---|---|
| LBBAP vs. CRT (RCT data) | Multiple ongoing RCTs; current data mostly observational |
| Leadless dual-chamber pacing | Micra AV approved; larger trials underway |
| Conduction system pacing in non-LBBB | Uncertain benefit; 2025 meta-analysis (PMID: 40731870) shows no advantage over BiV in non-LBBB |
| Cardioneuroablation vs. pacemaker | Head-to-head RCTs needed |
| MRI-conditional all-pacemaker systems | Near universal; specific protocols still center-dependent |
| AI-guided pacemaker programming | Emerging; no formal guidelines yet |
| Guideline | Year | Society | Focus |
|---|---|---|---|
| Bradycardia & Conduction Delay | 2018 | ACC/AHA/HRS | Core indications, mode selection |
| Cardiac Physiologic Pacing | 2023 | HRS/APHRS/LAHRS | CRT, CSP, LBBAP, HBP |
| Cardioneuroablation | 2024 | EHRA/HRS/APHRS/LAHRS | CNA as pacemaker alternative |
| 2026 EP Training Standards | 2026 | ACC/AHA/HRS | Training + competency in CSP |
Important note on the 2018 ACC/AHA/HRS guideline: As of mid-2026, this remains the primary reference for bradycardia indications. The 2023 HRS guideline specifically updates the physiologic pacing strategy and CRT indications but does not replace the 2018 document for fundamental pacemaker indications (sinus node dysfunction, AV block criteria, etc.). Always use both documents together.
Create a comparison table: CSP (HBP/LBBAP) vs CRT vs RV pacing with outcomes
"conduction system pacing" AND "biventricular" AND "right ventricular pacing" AND outcomes
"left bundle branch area pacing" AND "ejection fraction" AND comparison
PMID: 42092782
PMID: 40644356
PMID: 40835365
PMID: 40880214
PMID: 41038277
Evidence synthesized from the 2023 HRS/APHRS/LAHRS Guideline (PMID: 37283271), the CSPACE RCT (JACC 2025, PMID: 40835365), the TREEBEARD registry-RCT (Europace 2025, PMID: 40880214), a 2026 meta-analysis in BMC Cardiovasc Disord (19 studies, n=5,390; PMID: 42092782), a 2024 Heart Rhythm meta-analysis of 7 RCTs (PMID: 38382686), and a 2026 PACE meta-analysis for PICM (PMID: 41968613).
| Feature | RV Pacing | CRT (BiV Pacing) | HBP | LBBAP |
|---|---|---|---|---|
| Mechanism | Electrical stimulus to RV apex or septum; non-physiologic spread via myocardium | Simultaneous LV (via coronary sinus) + RV pacing; narrows QRS externally | Direct His bundle stimulation; uses native conduction system below the bundle | Deep septal pacing engages left bundle branch fascicles; more distal than HBP |
| Lead count | 1 (RV) | 2-3 (RA + RV + LV) | 1-2 (His lead ± RV backup) | 1-2 (LBB lead ± RV backup) |
| Lead position | RV apex or septum | RV apex + coronary sinus (LV) + RA | Membranous/para-Hisian septum | Deep interventricular septum (3.5-4.5 mm deep) |
| Ventricular activation | Abnormal (LBBB-like), ~160-180 ms QRS | Near-normal, 120-140 ms; depends on LV lead position | Narrow (native conduction), typically <130 ms; corrects LBBB | Narrow, 120-130 ms; slightly broader than HBP; corrects LBBB |
| Guideline class (bradycardia, high pacing burden) | Class I (standard), but Class IIa for minimization | Class I when LVEF ≤35% + LBBB + QRS ≥150 ms | Class IIa (alternative to CRT or when CRT not feasible) | Class IIa (preferred CSP method) |
| Year of guideline endorsement | Decades; foundational | 2018 ACC/AHA/HRS | 2023 HRS guideline | 2023 HRS guideline |
| Outcome | RV Pacing | CRT (BiV) | HBP | LBBAP |
|---|---|---|---|---|
| Paced QRS duration | 160-185 ms (LBBB-like morphology) | 120-140 ms (-30 to -40 ms vs. RVP) | 100-130 ms (near-native); narrows by ~50-60 ms vs. baseline | 110-135 ms; narrows by ~45-55 ms vs. RVP |
| QRS narrowing vs. RVP (meta-analysis) | Reference | ~-30 ms | -53 ms (PICM meta-analysis, PMID: 41968613) | -53 ms (combined CSP estimate) |
| QRS narrowing vs. BiV | - | Reference | -13 to -36 ms further reduction | -13 to -36 ms further reduction |
| LBBB correction | No; creates LBBB-like pattern | Partial (external resynchronization) | Yes - corrects native LBBB by pacing at or above block | Yes - corrects LBBB by engaging LBB below block |
| AV synchrony | Maintained in DDD | Maintained (with RA lead) | Maintained | Maintained |
| Outcome | RV Pacing | CRT (BiV) | CSP (combined) | Source |
|---|---|---|---|---|
| LVEF change vs. baseline | -3 to -5% (over time, high pacing burden) | +8-10% (RCTs in HFrEF) | +9-12% | Meta-analyses; Kaza et al. 2023 |
| LVEF change: CSP vs. BiV | - | Reference | +2.1% more (p=0.03) | Ferreira Felix et al. 2024 (PMID: 38382686) |
| LVEF change: CSP vs. RVP (AV block, meta-analysis) | Reference | - | +2.60% (p<0.0001) | Ahmed et al. 2026 (PMID: 42092782) |
| LV end-diastolic diameter (LVEDD) | Increases (adverse remodeling) | Decreases | -1.54 mm vs. RVP (p<0.0001) | Ahmed et al. 2026 (PMID: 42092782) |
| NYHA class improvement | Minimal | -0.8 to -1.2 | -1.0 to -1.2 | Kaza et al. 2023 |
| NYHA: CSP vs. BiV | - | Reference | -0.37 SMD (p=0.02) | Ferreira Felix et al. 2024 |
| NYHA: CSP vs. BiV (AVNA for AF) | - | Reference | -0.53 (p=0.03) | Mavilakandy et al. 2025 (PMID: 40644356) |
| 6-min walk / peak VO2 | Reduced vs. normal | +2.6 mL/kg/min (vs. no CRT) | Comparable to BiV; limited data | Various |
| Outcome | RV Pacing | CRT (BiV) | CSP (combined HBP+LBBAP) | Source |
|---|---|---|---|---|
| All-cause mortality | Reference (highest risk in high-pacing) | Reduced in HFrEF (NNT ~18 in CARE-HF, COMPANION) | RR 0.50 vs. RVP (p<0.0001) | Ahmed et al. 2026 (PMID: 42092782) |
| HF hospitalization | Reference | Reduced ~37% vs. RVP | RR 0.39 vs. RVP (p<0.0001) | Ahmed et al. 2026 |
| Pacing-induced cardiomyopathy (PICM) | 10-20% incidence with high pacing burden | Prevented when used upfront | RR 0.36 vs. RVP (p=0.039); 84.7% response rate vs. 67.6% BiV | Ahmed et al. 2026; Jin et al. 2026 (PMID: 41968613) |
| CRT upgrade required | 10-15% of patients over time | N/A (already CRT) | HR 0 vs. RVP (p=0.043; no upgrades needed) | CSPACE RCT 2025 (PMID: 40835365) |
| Composite PICM + CRT upgrade + HFH + mortality | Reference | - | HR 0.35 (65% relative risk reduction vs. RV septal pacing) | CSPACE RCT 2025 |
| CV death + HFH (LBBAP vs. RVP, <65 yrs) | Reference | - | HR 0.78 (22% RRR); driven by HFH reduction | TREEBEARD RCT 2025 (PMID: 40880214) |
| AF development | Higher incidence (atrial remodeling from dyssynchrony) | Reduced vs. RVP | Less data; expected benefit | Observational data |
| Feature | RV Pacing | CRT (BiV) | HBP | LBBAP |
|---|---|---|---|---|
| Procedure complexity | Simple (low) | Moderate-high (CS lead challenging) | High (small His target, steep learning curve) | Moderate (more forgiving than HBP) |
| Procedure time | Short (~45-60 min) | Long (~90-150 min) | Similar to BiV (longer than RVP) | ~60-90 min; comparable to BiV |
| Fluoroscopy time | Short | Longer | Longer than RVP | Longer than RVP |
| Success rate | ~100% | 85-95% (CS lead placement) | 80-90% (lower than LBBAP; His is small target) | 90-96% (higher than HBP) |
| Lead revision rate | Low ~1-2% | 3-5% (CS lead most prone) | 8-12% (high threshold drift over time) | 3-5% (improving with experience) |
| Pacing threshold at implant | Low (0.5-1.0 V) | Variable (CS lead: 1.0-2.5 V) | Higher (1.0-2.0 V; rises with time) | Lower than HBP (0.6-1.2 V) |
| Lead impedance stability | Stable | Moderate (CS lead variable) | Variable (fibrosis-related rise) | More stable than HBP |
| Backup ventricular lead needed | Not usually | Built-in RV lead | Often (for high-threshold backup) | Sometimes (if LBBAP threshold marginal) |
| Septal perforation risk | None | None | Rare | Low but possible (deep septal penetration) |
| Complication | RV Pacing | CRT (BiV) | HBP | LBBAP |
|---|---|---|---|---|
| Pneumothorax | ~1-2% | ~2% (BiV upgrade) | ~1-2% | ~1-2% |
| Cardiac tamponade | <1% | ~1.4% (BiV upgrade) | Rare | Low |
| Infection (pocket/lead) | ~1-2% | ~3.7% at 24 months (upgrades) | ~1-2% | ~1-2% |
| Threshold rise / exit block | Rare | Rare (CS lead variable) | More common (fibrosis, 8-12% lead issues) | Less common than HBP |
| Septal hematoma (LBBAP-specific) | None | None | None | Rare (<1%) |
| Phrenic nerve stimulation | None | 2-4% (LV lead) | Rare | Rare |
| Device-related adverse outcomes (PICM cohort) | 20.1% | - | 14.0% (CSP combined; p<0.001) | 14.0% (CSP combined; p<0.001) |
| Lead revision (CSPACE RCT) | 1% | - | 7.9% (CSP combined) | 7.9% |
| Clinical Scenario | Best Choice | Evidence Level | Rationale |
|---|---|---|---|
| AV block, normal LVEF, low pacing burden expected | RV pacing | Class I / Level C | Simple, safe, effective |
| AV block, expected pacing >40%, LVEF 36-50% | CSP (LBBAP preferred) | Class IIa / Level B | Prevents PICM; 2023 HRS guideline |
| AV block, expected pacing >40%, LVEF ≤35% | CRT or CSP | Class I / Level A (CRT); IIa (CSP) | CRT has strongest evidence; CSP emerging |
| HFrEF + LBBB + QRS ≥150 ms | CRT | Class I / Level A | MADIT-CRT, RAFT, CARE-HF, COMPANION |
| HFrEF + non-LBBB + QRS ≥130 ms | CRT (Class IIa) | IIa / B | Less robust evidence than LBBB subgroup |
| CRT non-responder (~30% of patients) | Upgrade to CSP (HBP or LBBAP) | Class IIa / Level B | CSP corrects true electrical dyssynchrony |
| Pacing-induced cardiomyopathy (PICM) | Upgrade to CSP preferred over BiV | IIa / B | CSP: 84.7% response rate vs. 67.6% BiV |
| AF + fast ventricular rate + failed rate control | AVNA + CSP (LBBAP preferred) | IIa / B | LBBAP + AVNA: better success rate than HBP |
| SSS with intact AV conduction | AAI(R) or DDD(R) standard RV pacing | Class I | CSP not routinely needed |
| Vasovagal syncope, cardioinhibitory type | Consider CNA (catheter-based) vs. pacemaker | IIb | Emerging EHRA/HRS 2024 statement |
| Feature | HBP | LBBAP | Winner |
|---|---|---|---|
| QRS narrowing | Greater (stimulates above LBBB) | Slightly less narrow | HBP |
| LBBB correction | Better correction | Good but slightly less | HBP |
| Success rate | 80-90% | 90-96% | LBBAP |
| Pacing threshold | Higher; rises over time | Lower; more stable | LBBAP |
| Lead revision rate | 8-12% | 3-5% | LBBAP |
| Procedural difficulty | Higher (small His target) | More manageable | LBBAP |
| Long-term reliability | Lower (threshold instability) | Higher | LBBAP |
| QRS duration at follow-up | Narrowest | Near-narrow | HBP (marginally) |
| Overall: 2023 HRS preference | IIa | IIa (preferred CSP method) | LBBAP |
Physiologic superiority:
HBP ≈ LBBAP > CRT (BiV) >> RV Pacing
Procedural reliability:
LBBAP > CRT (BiV) > HBP > RV Pacing
Evidence base (RCT volume):
CRT (BiV) >> LBBAP ≈ HBP >> RV Pacing (as comparator)
Guideline strength:
CRT (Class I, Level A) > LBBAP/HBP (Class IIa, Level B)
Key takeaway from the CSPACE RCT (JACC, Aug 2025): This landmark trial - the most rigorous RCT to date - showed CSP achieves a 65% relative reduction in the composite of PICM, CRT upgrade, HF hospitalization, and death vs. RV septal pacing (HR 0.35, p<0.001) in AV block. No patient in the CSP arm required CRT upgrade. This trial strongly supports upfront CSP as the preferred strategy when high pacing burden is anticipated.
LBBAP has now overtaken HBP as the preferred CSP modality due to higher success rates, lower thresholds, and fewer lead revisions - though HBP offers marginally narrower QRS when it works. The 2023 HRS guideline acknowledges this, and the 2026 ACC/AHA/HRS training statement designates LBBAP as "universally adopted."
Normal parameters inpacemaker
pacemaker programming parameters chart threshold sensing impedance

This image presents a multi-channel real-time telemetry recording of a ventricular pacing threshold analysis in VVI mode. It consists of five synchronous tracings: 1) Event markers at the top, where long vertical bars represent ventricular pacing spikes and short bars indicate atrial sensing. 2) Transvalvular impedance (TVI) tracing measured in Ohms (0–50 Ohm scale), serving as a hemodynamic sensor for ventricular ejection. 3–5) Simultaneous surface ECG recordings (leads I, III, and aVR) scaled to 0.15 mV. The sequence illustrates a capture failure at the sixth pacing spike, where the pulse energy falls below the threshold. Visually, the successful pacing in the first five beats is confirmed by periodic TVI waveform rises (indicating mechanical ejection) and wide QRS complexes on the ECG. Upon the sixth spike (capture failure), the TVI tracing remains flat at the diastolic baseline, and the ECG shows a pacing spike without an ensuing QRS complex. The final segments show the pacemaker's response by increasing pulse amplitude to restore effective ventricular stimulation and mechanical capture.

This diagnostic image displays real-time cardiac telemetry and surface ECG tracings (leads I, II, and aVR) during a ventricular pacing threshold analysis in VDD mode. The top tracing shows event markers: short vertical bars indicate atrial sensing, intermediate bars represent ventricular pacing pulses, and the longest bars signify ventricular sensing within the refractory period. The second tracing illustrates transvalvular impedance (TVI), used as a hemodynamic sensor to confirm ventricular ejection. Initially, the ECG shows wide QRS complexes evoked by ventricular pacing. From the fifth pulse onward, the stimulation intensity falls below the myocardial threshold, resulting in a transition to narrow QRS complexes indicative of intrinsic conduction. Despite the loss of electrical capture, the TVI tracing maintains rhythmic fluctuations, demonstrating that mechanical ventricular ejection continues via natural activation. This comparison highlights the clinical utility of TVI in distinguishing between electrical capture loss and the total absence of mechanical contraction, facilitating safer pacemaker autoregulation and capture surveillance.

Table 9 Pacemaker interrogation and programming approach for CPP <table><thead><tr><th></th><th>HBP</th><th>LBBAP</th><th>CRT</th></tr></thead><tbody><tr><td>Capture thresholds</td><td>Determine His bundle capture relative to RV capture; program output to ensure His bundle capture (at least 1 V above the threshold)</td><td>Determine LBB (LV septal) capture and anodal capture</td><td>Determine LV (CS lead)-only capture and anodal capture</td></tr><tr><td>Capture assessment algorithms</td><td>Avoid, unless known that His bundle and RV capture thresholds are similar</td><td>Capture assessment algorithms can be utilized successfully</td><td>Capture assessment algorithms can be utilized successfully; LV-only pacing may be preferred in some cases</td></tr><tr><td>AV delays</td><td>Program 30–50 ms shorter than conventional parameters*</td><td>Program 20–30 ms shorter than conventional parameters*</td><td>Program 10–20 ms shorter than conventional parameters*</td></tr><tr><td>Atrial oversensing</td><td>Atrial oversensing can occur with proximal lead placement and may need appropriate programming to also avoid ventricular undersensing</td><td></td><td></td></tr><tr><td>Ventricular unipolar sensing</td><td>Avoid if pacing dependent</td><td></td><td></td></tr></tbody></table>