This document tracks the budget of the Department of Health – Office of the Secretary (DOH-OSEC) across ten fiscal years, FY 2018 to FY 2027 — with FY 2027 the Executive’s proposal (NEP), not yet enacted — following each peso from proposal (NEP) to enactment (GAA) to release (allotment), commitment (obligation), and final cash payment (disbursement).
It is the long-form companion to the DOH-OSEC briefing deck. Where the deck fits each point on a slide, this version keeps the full argument and adds reference tables — most sortable, searchable, and exportable — so a reader can interrogate the figures directly. Every table can be copied or downloaded from its toolbar.
Two forces shape DOH-OSEC’s budget. The first is Congress: DOH has its budget enlarged by the legislature in every single year of this period, cumulatively by more than ₱210B, and those additions are heavily concentrated in a handful of flagship lines. The second is absorption, and specifically a capital-outlay bottleneck — the agency reliably spends its salaries and operating money but struggles to disburse its infrastructure budget, year after year. Most of what follows examines how those two forces interact: money is appropriated faster than the agency’s procurement and construction pipeline can spend it.
The FY 2027 proposal (NEP) is ₱264B for DOH-OSEC — up about ₱10B (+4%) on the FY 2026 proposal, and the largest DOH proposal yet: a rising, not shrinking, proposal. But it again sits far below what Congress enacts — the FY 2026 GAA was ₱298B, ₱44B above that year’s proposal. Read against DOH’s history of double-digit-billion augmentation, the FY 2027 NEP is best treated as a floor Congress will build on, not a ceiling.
The DOH-OSEC budget has nearly tripled in nominal terms, from a ₱107B enacted budget in 2018 to a proposed ₱298B in the 2026 GAA. Growth has been steady since the 2019 dip, with the largest single-year jumps in 2022 and 2026.
Congress augments DOH every year. The enacted GAA has exceeded the Executive’s NEP in every year of the period — by as little as ₱2B (2018) and as much as ₱44B (2026). Cumulatively, Congress has added about ₱210B on top of Executive proposals over 2018–2026. These additions are highly concentrated: MAIFIP alone absorbed ₱97B of cumulative plus-ups and the Health Facilities Enhancement Program (HFEP) another ₱56B — together over 70% of all Congressional augmentation to DOH-OSEC since 2018.
MAIFIP is the clearest case. Medical Assistance to Indigent and Financially-Incapacitated Patients grew roughly twelve-fold in the GAA, from ₱4.9B in 2018 to ₱58.1B in 2024, with Congressional plus-ups of ₱20–36B a year accounting for most of the increase. But disbursement lags: in 2024 MAIFIP obligated 85% of its allotment yet paid out only 55%.
The absorption problem is mostly a Capital Outlay problem. Personnel Services disburses at ~98% every year and MOOE at 50–70%, but Capital Outlays disburse at only 14–37% — and CO disbursement has been deteriorating since 2021. HFEP, which is almost entirely capital outlay, has never disbursed more than 32% of its allotment in any year on record; its cumulative unspent allotment over 2018–2025 is roughly ₱109B.
The portfolio is rebalancing toward MOOE: the MOOE
share of the GAA rose from 39% in 2018 to 53% in 2026, while the Capital
Outlay share fell from 29% to 13%. Congressional augmentation is
overwhelmingly MOOE-bound (about ₱125B of the ₱210B cumulative plus-up).
And hospital operations dominate the functional
composition and are growing fastest in absolute terms; the 2025
PREXC reorganization split the public-health side into a
policy/strategy program (3501) and a
local-health-system-support program (3502).
The recurring tension: Congress routes its largest additions into MOOE and into capital-heavy flagships like HFEP, but the agency’s binding constraint is its ability to disburse — especially on infrastructure. Appropriating more does not, on this record, translate one-for-one into spending.
Period. FY 2018 through FY 2027 for NEP and FY 2018 through FY 2026 for GAA — FY 2027 is the NEP (the Executive’s proposal) only, not yet debated or enacted and with no execution data, so wherever a chart or table shows FY 2027 the figure is proposed. Execution data — Adjusted Appropriations, Adjusted Allotments, Obligations, Disbursements — is available at the P/A/P level for every year FY 2018–2025; FY 2026 reflects the proposed/enacted budget only.
Scope. Current New Appropriations only — excludes Continuing Appropriations, Automatic Appropriations, and transfers from Special Purpose Funds and Unprogrammed Appropriations. These figures therefore understate the DOH’s full spending envelope. All amounts are nominal pesos.
2025 PREXC re-coding. DOH renumbered its program
codes in 2025. Where the same P/A/P appears under both an old and a new
UACS code — 3201→3601 (hospitals),
3301→3701 (regulation),
3401→3801 (patient assistance) — the two are
treated as the same line. The public-health programs
3101–3105 were reorganized into
3501 and 3502; see the
reorganization section.
Two P/A/P renames consolidated. “Assistance to
Indigent Patients…” → MAIFIP, and “HRH Deployment”
(3102) → NHWSS (re-coded and renamed in
2022). Both are reported as single continuous lines throughout.
Absorptive-capacity denominator. Unless noted, ratios use Adjusted Allotments — the closest proxy for what the agency was actually cleared to spend. The three ratios are O/A (Obligations ÷ Allotment), D/O (Disbursements ÷ Obligations), and D/A (Disbursements ÷ Allotment).
evo <- totals_by_year %>%
filter(metric %in% c("NEP","GAA","AdjAllot","Obligations","Disbursements")) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP (proposed)","GAA (enacted)","Adj. Allotment","Obligations","Disbursements")))
ggplot(evo, aes(year, total, color = metric, group = metric)) +
geom_line(linewidth = 1.0) + geom_point(size = 2) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = c(seq(2018, 2026, 2), 2027)) +
annotate("text", x = 2027, y = Inf, label = "proposed", vjust = 1.4, size = 3, color = "grey45") +
labs(title = "DOH-OSEC budget, NEP through Disbursements (FY 2018–2027)",
subtitle = "GAA has nearly tripled since 2018; disbursements lag persistently behind allotments; the FY 2027 NEP proposes ~PHP 264B",
x = NULL, y = NULL, caption = "FY 2027 is the NEP (proposed) only; FY 2026 reflects NEP/GAA only; execution runs through 2025.") +
theme_doh() + guides(color = guide_legend(nrow = 1))
Two features stand out and organize the rest of this report. First, the NEP and GAA lines separate visibly in most years — the enacted budget sits above the Executive’s proposal, the signature of an agency Congress consistently augments (the next sections quantify it). Second, the disbursement line trails the allotment line by a wide and persistent margin: DOH releases money it does not fully pay out within the year. The table gives the underlying figures.
tbl_evo <- totals_by_year %>%
filter(metric %in% c("NEP","GAA","AdjAllot","Obligations","Disbursements")) %>%
mutate(value = total/1e9) %>% select(year, metric, value) %>%
pivot_wider(names_from = year, values_from = value) %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP","GAA","Adj. Allotment","Obligations","Disbursements"))) %>%
arrange(metric) %>% rename(`PHP B` = metric)
kbl_clean(tbl_evo, font = 13, digits = 1, format.args = list(big.mark = ","), na = "")
| PHP B | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | 2027 |
|---|---|---|---|---|---|---|---|---|---|---|
| NEP | 104.7 | 71.0 | 88.7 | 127.8 | 157.5 | 191.2 | 199.5 | 217.8 | 253.8 | 264 |
| GAA | 107.2 | 98.6 | 101.0 | 134.9 | 183.9 | 209.6 | 241.6 | 247.9 | 297.9 | |
| Adj. Allotment | 102.9 | 93.1 | 98.7 | 134.5 | 180.6 | 208.8 | 230.5 | 225.3 | ||
| Obligations | 96.7 | 82.9 | 86.7 | 126.3 | 156.9 | 191.4 | 209.9 | 192.9 | ||
| Disbursements | 54.8 | 61.2 | 70.0 | 98.4 | 122.4 | 154.6 | 167.0 | 156.5 |
The disbursement story is two-sided. The disbursement-to-allotment ratio has improved from a low of 53% (2018) to roughly 70% in 2021–2025 — the agency has gotten better at converting releases into payments. But the absolute disbursement gap has roughly doubled, from about ₱48B in 2018 to ₱69B in 2025, simply because the budget scaled so much. A better rate on a far larger base still leaves more money unspent.
The budget contracted in 2019 — a re-enactment year following a budget impasse — and grew every year after. The table pairs each year’s GAA growth with the size of the Congressional add-on (GAA minus NEP), the recurring feature of the DOH budget.
wide_yr <- totals_by_year %>% pivot_wider(names_from = metric, values_from = total)
growth <- wide_yr %>% arrange(year) %>%
transmute(year,
`GAA (B)` = round(GAA/1e9,1),
`Growth %` = scales::percent(GAA/lag(GAA) - 1, accuracy = 0.1),
`NEP (B)` = round(NEP/1e9,1),
`Augmentation GAA−NEP (B)` = round((GAA-NEP)/1e9,1))
kbl_clean(growth, font = 13, align = "rrrrr", na = "")
| year | GAA (B) | Growth % | NEP (B) | Augmentation GAA−NEP (B) |
|---|---|---|---|---|
| 2018 | 107.2 | 104.7 | 2.5 | |
| 2019 | 98.6 | -8.1% | 71.0 | 27.5 |
| 2020 | 101.0 | 2.5% | 88.7 | 12.3 |
| 2021 | 134.9 | 33.6% | 127.8 | 7.2 |
| 2022 | 183.9 | 36.3% | 157.5 | 26.3 |
| 2023 | 209.6 | 14.0% | 191.2 | 18.4 |
| 2024 | 241.6 | 15.3% | 199.5 | 42.1 |
| 2025 | 247.9 | 2.6% | 217.8 | 30.2 |
| 2026 | 297.9 | 20.1% | 253.8 | 44.0 |
| 2027 | 264.0 |
The augmentation column is positive in every year — the defining characteristic of the DOH-OSEC budget.
A structural caveat that shapes several charts below. In 2025 DOH
renumbered its program codes. Most changes were simple
renumbering with unchanged scope —
3201→3601 (Hospital Operations),
3301→3701 (Regulation),
3401→3801 (Social Health Protection) — and are
transparently consolidated here. The substantive change was a
split: the old five public-health programs
(3101–3105, covering policy, systems, public
health, epidemiology, and emergencies) were collapsed into two new
programs along a policy/strategy versus local implementation
dividing line.
reorg <- tibble::tribble(
~`P/A/P`, ~`Old (pre-2025)`, ~`New (2025+)`,
"Health Sector Policy and Plan Development", "3101 Health Policy and Standards", "3501 Policy & Systems Strengthening",
"Pharmaceutical Management", "3102 Health Systems Strengthening", "3501 Policy & Systems Strengthening",
"Health Promotion", "3102 Health Systems Strengthening", "3501 Policy & Systems Strengthening",
"Epidemiology and Surveillance", "3104 Epidemiology and Surveillance", "3501 Policy & Systems Strengthening",
"Quick Response Fund", "3105 Health Emergency Management", "3501 Policy & Systems Strengthening",
"Health Facilities Enhancement Program (HFEP)", "3102 Health Systems Strengthening", "3502 Local Health System Support",
"National Health Workforce Support System (NHWSS)", "3102 Health Systems Strengthening", "3502 Local Health System Support",
"Nationally-procured Commodities (5 new lines)", "(part of 3103 programs)", "3502 Local Health System Support"
)
kbl_clean(reorg, font = 13, align = "lll", na = "")
| P/A/P | Old (pre-2025) | New (2025+) |
|---|---|---|
| Health Sector Policy and Plan Development | 3101 Health Policy and Standards | 3501 Policy & Systems Strengthening |
| Pharmaceutical Management | 3102 Health Systems Strengthening | 3501 Policy & Systems Strengthening |
| Health Promotion | 3102 Health Systems Strengthening | 3501 Policy & Systems Strengthening |
| Epidemiology and Surveillance | 3104 Epidemiology and Surveillance | 3501 Policy & Systems Strengthening |
| Quick Response Fund | 3105 Health Emergency Management | 3501 Policy & Systems Strengthening |
| Health Facilities Enhancement Program (HFEP) | 3102 Health Systems Strengthening | 3502 Local Health System Support |
| National Health Workforce Support System (NHWSS) | 3102 Health Systems Strengthening | 3502 Local Health System Support |
| Nationally-procured Commodities (5 new lines) | (part of 3103 programs) | 3502 Local Health System Support |
The practical consequence: several public-health lines that existed under the old codes disappear in 2025 and reappear as new-coded lines, which is why some of the low-absorber trajectories later in this report stop in 2024. Throughout, old and new codes are rolled into one functional bucket so the aggregate trends remain continuous.
Grouping P/A/Ps into six functional categories shows what kind of agency DOH-OSEC is. The chart shows the enacted budget by category; the tables give pesos and shares.
comp <- df_long %>%
filter(metric == "GAA", year <= 2026, !is.na(amount)) %>%
group_by(year, category) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(category = factor(category, levels = names(cat_pal)))
ggplot(comp, aes(year, amount, fill = category)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = cat_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "Composition of the GAA by functional category, 2018–2026",
subtitle = "Hospital operations and social health protection dominate; both growing fastest",
x = NULL, y = NULL) +
theme_doh() + guides(fill = guide_legend(nrow = 2, byrow = TRUE))
Hospital Operations is the largest and fastest-growing block in absolute terms — DOH-OSEC runs the country’s regional and specialty hospitals directly, and that operational footprint expands every year. Social Health Protection, which houses MAIFIP, is the next major growth story and the most Congress-driven. The public-health-and-programs category is large but structurally fragmented, which is what the 2025 reorganization tried to address.
comp_tbl <- comp %>% group_by(year) %>% mutate(share = amount/sum(amount)) %>% ungroup()
comp_amt <- comp_tbl %>% mutate(amount = round(amount/1e9,1)) %>%
select(category, year, amount) %>% pivot_wider(names_from = year, values_from = amount)
kbl_clean(comp_amt %>% rename(`Category (PHP B)` = category),
font = 12, digits = 1, format.args = list(big.mark=","), na = "")
| Category (PHP B) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| General Admin & Support | 9.0 | 8.5 | 6.7 | 8.1 | 8.4 | 12.7 | 13.5 | 14.5 | 18.2 |
| Health Policy, Public Health & Programs | 63.0 | 45.3 | 38.5 | 57.4 | 92.0 | 91.4 | 92.7 | 85.5 | 87.0 |
| Health Regulation | 0.8 | 0.8 | 0.9 | 1.1 | 1.0 | 1.1 | 1.1 | 1.3 | 1.4 |
| Hospital Operations | 27.5 | 32.5 | 42.0 | 49.3 | 56.4 | 68.6 | 71.5 | 100.8 | 136.0 |
| Social Health Protection (incl. MAIFIP) | 4.9 | 9.4 | 10.5 | 17.1 | 21.9 | 33.4 | 59.6 | 42.4 | 54.1 |
| Support to Operations | 2.2 | 2.0 | 2.4 | 1.9 | 4.2 | 2.3 | 3.2 | 3.3 | 1.1 |
comp_pct <- comp_tbl %>% mutate(share = round(share*100,1)) %>%
select(category, year, share) %>% pivot_wider(names_from = year, values_from = share)
Share of each year’s total budget:
kbl_clean(comp_pct %>% rename(`Category (% of GAA)` = category), font = 12, digits = 1, na = "")
| Category (% of GAA) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| General Admin & Support | 8.4 | 8.6 | 6.6 | 6.0 | 4.6 | 6.1 | 5.6 | 5.9 | 6.1 |
| Health Policy, Public Health & Programs | 58.7 | 46.0 | 38.1 | 42.5 | 50.1 | 43.6 | 38.4 | 34.5 | 29.2 |
| Health Regulation | 0.7 | 0.8 | 0.9 | 0.8 | 0.5 | 0.5 | 0.4 | 0.5 | 0.5 |
| Hospital Operations | 25.7 | 33.0 | 41.6 | 36.5 | 30.7 | 32.7 | 29.6 | 40.7 | 45.7 |
| Social Health Protection (incl. MAIFIP) | 4.5 | 9.5 | 10.4 | 12.7 | 11.9 | 15.9 | 24.7 | 17.1 | 18.2 |
| Support to Operations | 2.0 | 2.1 | 2.4 | 1.4 | 2.3 | 1.1 | 1.3 | 1.3 | 0.4 |
The same budget by what the money buys. The defining DOH-OSEC trend is a steady shift from Capital Outlay toward MOOE.
ec_levels <- c("Personnel Services (PS)","Maintenance & Other Op. Exp. (MOOE)","Capital Outlays (CO)")
comp_ec <- df_long_all %>%
filter(metric == "GAA", year <= 2026, expense_class %in% c("1PS","2MOOE","6CO")) %>%
group_by(year, expense_class) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
mutate(expense_class = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels))
ggplot(comp_ec, aes(year, amount, fill = expense_class)) +
geom_col(width = 0.75, color = "white", linewidth = 0.2) +
scale_fill_manual(values = ec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "GAA composition by Expense Class, 2018–2026",
subtitle = "MOOE share has grown from 39% (2018) to 53% (2026); Capital Outlays share fell from 29% to 13%",
x = NULL, y = NULL) +
theme_doh() + guides(fill = guide_legend(nrow = 1))
The MOOE share of the enacted budget rose from 39% in 2018 to 53% in 2026, while the Capital Outlay share fell from 29% to 13%. This matters because, as the absorption section shows, MOOE disburses far more reliably than CO — so the rebalancing is, incidentally, a shift toward more spendable money. Whether that is by design or a byproduct of Congress’s MOOE-heavy augmentation preferences is an open question.
ec_share <- comp_ec %>% group_by(year) %>% mutate(share = round(amount/sum(amount)*100,1)) %>% ungroup() %>%
select(expense_class, year, share) %>% pivot_wider(names_from = year, values_from = share)
kbl_clean(ec_share %>% rename(`Expense class (% of GAA)` = expense_class), font = 12.5, digits = 1, na = "")
| Expense class (% of GAA) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 |
|---|---|---|---|---|---|---|---|---|---|
| Personnel Services (PS) | 31.8 | 43.8 | 45.8 | 45.4 | 38.6 | 35.5 | 32.9 | 33.1 | 34.6 |
| Maintenance & Other Op. Exp. (MOOE) | 39.0 | 39.2 | 42.1 | 43.8 | 46.8 | 49.4 | 54.1 | 50.1 | 52.9 |
| Capital Outlays (CO) | 29.1 | 17.1 | 12.1 | 10.9 | 14.7 | 15.0 | 13.0 | 16.8 | 12.5 |
top_pap <- pap_year %>% filter(year == 2027) %>% arrange(desc(NEP)) %>% slice_head(n = 10) %>%
mutate(pap = factor(pap, levels = rev(pap)))
ggplot(top_pap, aes(pap, NEP)) +
geom_col(fill = "#54278F", width = 0.75) +
geom_text(aes(label = php_b(NEP)), hjust = -0.1, size = 3.3, color = "grey20") +
coord_flip() +
scale_x_discrete(labels = function(x) str_wrap(x, 50)) +
scale_y_continuous(labels = php_b_axis, expand = expansion(mult = c(0, .18))) +
labs(title = "Top 10 P/A/Ps by FY 2027 NEP (proposed)",
subtitle = "Regional Hospitals alone is over PHP 100B; MAIFIP and HFEP are proposed flat, still near the top",
x = NULL, y = NULL) +
theme_doh() +
theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))
Every P/A/P, ranked by the FY 2027 proposal (NEP), shown against the FY 2026 proposal and enacted budget, with each line’s FY 2025 cash-execution rate (D/A). Sort, search, or export.
ref_2027 <- pap_year %>% filter(year == 2027) %>%
transmute(`P/A/P` = pap, `NEP 2027 (B)` = NEP/1e9)
nep_gaa_26 <- pap_year %>% filter(year == 2026) %>%
transmute(`P/A/P` = pap, `NEP 2026 (B)` = NEP/1e9, `GAA 2026 (B)` = GAA/1e9)
da_25 <- pap_year %>% filter(year == 2025) %>%
transmute(`P/A/P` = pap, `D/A 2025` = Disbursements / AdjAllot)
ref_2027 <- ref_2027 %>%
left_join(nep_gaa_26, by = "P/A/P") %>% left_join(da_25, by = "P/A/P") %>%
arrange(desc(`NEP 2027 (B)`))
dt_table(ref_2027, page = 15,
money_cols = c("NEP 2027 (B)","NEP 2026 (B)","GAA 2026 (B)"),
pct_cols = c("D/A 2025"))
Comparing the two proposals — the FY 2026 NEP against the FY 2027 NEP — isolates what the Executive itself chose to change, before Congress touches the budget. MAIFIP and HFEP do not appear here at all: both are proposed essentially flat (~₱24B and ~₱15B again), so any apparent “cut” in those lines exists only against the Congress-inflated 2026 GAA, not against the Executive’s own prior proposal.
nep_change <- pap_year %>%
filter(year %in% c(2026, 2027)) %>%
select(pap, year, NEP) %>%
pivot_wider(names_from = year, values_from = NEP, names_prefix = "y") %>%
mutate(change = (y2027 - y2026) / 1e9) %>%
filter(!is.na(change), abs(change) >= 0.3)
ups <- nep_change %>% filter(change > 0) %>% arrange(desc(change)) %>% slice_head(n = 8)
downs <- nep_change %>% filter(change < 0) %>% arrange(change) %>% slice_head(n = 6)
nep_change <- bind_rows(ups, downs) %>% arrange(desc(change)) %>%
mutate(pap = factor(pap, levels = rev(pap)),
dir = ifelse(change >= 0, "Increased", "Reduced"))
ggplot(nep_change, aes(pap, change, fill = dir)) +
geom_col(width = 0.72) +
geom_text(aes(label = sprintf("%+.1f", change),
hjust = ifelse(change >= 0, -0.15, 1.15)),
size = 3, color = "grey25") +
coord_flip() +
scale_fill_manual(values = c("Increased" = "#1B7837", "Reduced" = "#D95F02")) +
scale_x_discrete(labels = function(x) str_wrap(x, 46)) +
scale_y_continuous(labels = function(x) paste0(peso, x, "B"),
expand = expansion(mult = c(0.16, 0.16))) +
labs(title = "What the Executive changed: FY 2026 NEP to FY 2027 NEP (PHP B)",
subtitle = "Proposal-to-proposal change, so Congressional augmentation is stripped out; MAIFIP and HFEP are proposed flat",
x = NULL, y = NULL) +
theme_doh() +
theme(panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(color = "grey85"),
legend.position = "none")
The biggest single increase is Regional Hospitals (+₱7.6B), consistent with a proposal that leans further into direct hospital operations; the Cancer Assistance Fund triples (from ₱1.25B to ₱3.75B), and the health workforce (NHWSS, +₱2.0B) and personnel benefits (+₱2.7B) also rise. The reductions are smaller and land on health information technology (−₱1.8B) and several nationally-procured commodity lines. Because MAIFIP and HFEP — the two lines Congress most reliably augments — are held flat in the proposal, the real FY 2027 budget for those programs will again be settled at enactment, not in the NEP.
Congress augments DOH year after year. The chart ranks the ten P/A/Ps that have received the most cumulative plus-ups (GAA above NEP) over 2018–2026.
top_aug <- pap_year %>% filter(year <= 2026) %>% group_by(pap) %>%
summarise(total_nep = sum(NEP, na.rm = TRUE), total_gaa = sum(GAA, na.rm = TRUE), .groups = "drop") %>%
mutate(augment = total_gaa - total_nep) %>% filter(augment > 0) %>%
arrange(desc(augment)) %>% slice_head(n = 10) %>% mutate(pap = factor(pap, levels = rev(pap)))
ggplot(top_aug, aes(pap, augment)) +
geom_col(fill = "#D95F02", width = 0.75) +
geom_text(aes(label = paste0("+", php_b(augment))), hjust = -0.1, size = 3.3, color = "grey20") +
coord_flip() +
scale_x_discrete(labels = function(x) str_wrap(x, 50)) +
scale_y_continuous(labels = php_b_axis, expand = expansion(mult = c(0, .22)), limits = c(0, NA)) +
labs(title = "Cumulative NEP-to-GAA increase, 2018–2026",
subtitle = "MAIFIP and HFEP alone absorbed PHP 153B in plus-ups — over 70% of all DOH-OSEC augmentation",
x = NULL, y = NULL) +
theme_doh() +
theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))
Congress’s additions are strikingly concentrated. MAIFIP (₱97B cumulative) and HFEP (₱56B) together account for ₱153B — more than 70% of all DOH-OSEC augmentation since 2018. One is a cash-assistance (MOOE) line that disburses moderately; the other is a construction (capital-outlay) line that barely disburses at all. The legislature’s two favorite programs to fund are, respectively, the agency’s largest discretionary transfer and its deepest execution bottleneck.
The full cumulative table lists every P/A/P that Congress net-augmented over the nine years.
aug_full <- pap_year %>% filter(year <= 2026) %>% group_by(pap) %>%
summarise(nep = sum(NEP, na.rm = TRUE), gaa = sum(GAA, na.rm = TRUE), .groups = "drop") %>%
mutate(aug = gaa - nep) %>% filter(abs(aug) >= 1e8) %>%
transmute(`P/A/P` = pap, `Σ NEP 2018–26 (B)` = nep/1e9, `Σ GAA 2018–26 (B)` = gaa/1e9,
`Cumulative augmentation (B)` = aug/1e9) %>%
arrange(desc(`Cumulative augmentation (B)`))
dt_table(aug_full, page = 10,
money_cols = c("Σ NEP 2018–26 (B)","Σ GAA 2018–26 (B)","Cumulative augmentation (B)"))
Congress’s fiscal preference is operating-expense-heavy. Splitting the cumulative plus-up by expense class shows it goes overwhelmingly to MOOE — commodities, cash-assistance lines, and contracted services — rather than to salaries or infrastructure.
aug_ec <- df_long_all %>%
filter(metric %in% c("NEP","GAA"), year <= 2026, expense_class %in% c("1PS","2MOOE","6CO")) %>%
group_by(metric, expense_class) %>% summarise(a = sum(amount, na.rm = TRUE), .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = a) %>%
transmute(`Expense class` = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels),
`Σ NEP 2018–26 (B)` = round(NEP/1e9,1),
`Σ GAA 2018–26 (B)` = round(GAA/1e9,1),
`Cumulative augmentation (B)` = round((GAA-NEP)/1e9,1)) %>% arrange(`Expense class`)
kbl_clean(aug_ec, font = 13, align = "lrrr", na = "")
| Expense class | Σ NEP 2018–26 (B) | Σ GAA 2018–26 (B) | Cumulative augmentation (B) |
|---|---|---|---|
| Personnel Services (PS) | 577.7 | 594.7 | 17.0 |
| Maintenance & Other Op. Exp. (MOOE) | 658.9 | 784.1 | 125.2 |
| Capital Outlays (CO) | 175.5 | 243.9 | 68.4 |
Medical Assistance to Indigent and Financially-Incapacitated Patients is the single most consequential line in the DOH-OSEC budget’s recent history. It pays hospital bills for poor patients, and it has grown explosively — almost entirely on the strength of Congressional plus-ups.
maifip <- pap_year %>% filter(pap == MAIFIP_LAB) %>%
select(year, NEP, GAA, AdjAllot, Obligations, Disbursements) %>%
pivot_longer(-year, names_to = "metric", values_to = "amount") %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP (proposed)","GAA (enacted)","Adj. Allotment","Obligations","Disbursements")))
ggplot(maifip, aes(year, amount, color = metric, group = metric)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.8) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6),
limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = c(seq(2018, 2026, 2), 2027)) +
annotate("text", x = 2027, y = Inf, label = "proposed", vjust = 1.4, size = 3, color = "grey45") +
labs(title = "MAIFIP: from PHP 4.9B (2018) to PHP 58B (2024 GAA)",
subtitle = "Congressional plus-ups dwarf the Executive's proposal year after year",
x = NULL, y = NULL,
caption = "MAIFIP unifies the old 'Assistance to Indigent Patients in Government Hospitals' line with the current MAIFIP label.") +
theme_doh() + guides(color = guide_legend(nrow = 1))
The GAA grew roughly twelve-fold, from ₱4.9B in 2018 to ₱58.1B in 2024, and in most years the gap between proposal and enactment is enormous: in 2024 the ₱22.3B NEP became a ₱58.1B GAA (a ₱36B plus-up); in 2026 a ₱24.2B NEP becomes a ₱51.7B GAA (₱27B). But execution tells a more cautious story — the program obligates well but disburses with a real lag, as the table makes explicit.
In the FY 2027 proposal the Executive again proposes ₱24.2B for MAIFIP — essentially identical to its FY 2026 proposal, and roughly the figure it has put forward for three years running. If the established pattern holds, Congress will again roughly double it at enactment. Reading the ₱24.2B proposal as a cut against the ₱51.7B FY 2026 GAA would be a proposal-versus-enacted error: the Executive is not shrinking MAIFIP, it is under-proposing a line it fully expects Congress to restore. That keeps the annual restoration a live advocacy question rather than a foregone conclusion — and sharpens the deeper one of whether MAIFIP is functioning as a de facto substitute for PhilHealth case-rate coverage or as a discretionary assistance line.
pap_year %>% filter(pap == MAIFIP_LAB, year %in% 2018:2025) %>%
transmute(FY = year, `NEP (B)` = round(NEP/1e9,1), `GAA (B)` = round(GAA/1e9,1),
`Allotment (B)` = round(AdjAllot/1e9,1), `Obligated (B)` = round(Obligations/1e9,1),
`Disbursed (B)` = round(Disbursements/1e9,1),
`O/A` = scales::percent(Obligations/AdjAllot, accuracy = 1),
`D/A` = scales::percent(Disbursements/AdjAllot, accuracy = 1)) %>%
kbl_clean(font = 13, align = "rrrrrrrr", na = "")
| FY | NEP (B) | GAA (B) | Allotment (B) | Obligated (B) | Disbursed (B) | O/A | D/A |
|---|---|---|---|---|---|---|---|
| 2018 | 4.3 | 4.9 | 4.9 | 4.8 | 3.2 | 98% | 66% |
| 2019 | 5.6 | 9.4 | 9.4 | 7.5 | 6.2 | 80% | 66% |
| 2020 | 9.4 | 10.5 | 9.4 | 7.2 | 4.9 | 76% | 52% |
| 2021 | 17.3 | 17.0 | 17.0 | 12.4 | 7.4 | 73% | 43% |
| 2022 | 17.0 | 21.4 | 21.4 | 17.3 | 12.8 | 81% | 60% |
| 2023 | 22.4 | 32.6 | 32.6 | 29.5 | 23.0 | 90% | 71% |
| 2024 | 22.3 | 58.1 | 58.1 | 49.6 | 31.7 | 85% | 55% |
| 2025 | 26.9 | 41.2 | 41.2 | 33.9 | 25.3 | 82% | 61% |
In 2024 MAIFIP obligated ₱49.6B of its ₱58.1B allotment (85%) but disbursed only ₱31.7B (55%). Even in 2018, on a far smaller ₱4.9B base, it disbursed only about two-thirds. The open question is what MAIFIP is: a de facto substitute for PhilHealth case-rate coverage, or a discretionary assistance line whose size is set politically rather than by demand. The persistent proposal-versus-enacted gap is consistent with the latter dynamic.
At the whole-office level, obligation rates hold near 90% while disbursement rates have climbed from 53% (2018) to about 70% in recent years — an improving but still incomplete conversion of releases into cash.
absorp_long <- absorp_total %>% select(year, oblig_allot, disb_oblig, disb_allot) %>%
pivot_longer(-year, names_to = "ratio", values_to = "value") %>%
mutate(ratio = factor(ratio, levels = c("oblig_allot","disb_oblig","disb_allot"),
labels = c("Obligations / Adj. Allotment","Disbursements / Obligations","Disbursements / Adj. Allotment")))
ggplot(absorp_long, aes(year, value, color = ratio, group = ratio)) +
geom_line(linewidth = 0.9) + geom_point(size = 2) +
geom_text(aes(label = scales::percent(value, accuracy = 1)), vjust = -1.0, size = 3.0, show.legend = FALSE, color = "grey20") +
scale_color_manual(values = absorp_pal) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.0), breaks = seq(0, 1, 0.2)) +
scale_x_continuous(breaks = 2018:2025) +
labs(title = "DOH-OSEC absorptive capacity, 2018–2025",
subtitle = "Disbursement rates have improved from 53% (2018) to ~70%; obligation rates hold near 90%",
x = NULL, y = NULL) +
theme_doh() + guides(color = guide_legend(nrow = 1))
absorp_total %>%
transmute(Year = year, `Allotment (B)` = round(AdjAllot/1e9,1),
`Obligations (B)` = round(Obligations/1e9,1), `Disbursements (B)` = round(Disbursements/1e9,1),
`O/A` = scales::percent(oblig_allot, accuracy = 1),
`D/O` = scales::percent(disb_oblig, accuracy = 1),
`D/A` = scales::percent(disb_allot, accuracy = 1)) %>%
kbl_clean(font = 13, align = "rrrrrrr", na = "")
| Year | Allotment (B) | Obligations (B) | Disbursements (B) | O/A | D/O | D/A |
|---|---|---|---|---|---|---|
| 2018 | 102.9 | 96.7 | 54.8 | 94% | 57% | 53% |
| 2019 | 93.1 | 82.9 | 61.2 | 89% | 74% | 66% |
| 2020 | 98.7 | 86.7 | 70.0 | 88% | 81% | 71% |
| 2021 | 134.5 | 126.3 | 98.4 | 94% | 78% | 73% |
| 2022 | 180.6 | 156.9 | 122.4 | 87% | 78% | 68% |
| 2023 | 208.8 | 191.4 | 154.6 | 92% | 81% | 74% |
| 2024 | 230.5 | 209.9 | 167.0 | 91% | 80% | 72% |
| 2025 | 225.3 | 192.9 | 156.5 | 86% | 81% | 69% |
Decomposing the aggregate by expense class locates the problem precisely.
absorp_ec <- df_long_all %>%
filter(metric %in% c("AdjAllot","Disbursements"), expense_class %in% c("1PS","2MOOE","6CO"), year %in% 2018:2025) %>%
group_by(year, metric, expense_class) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
pivot_wider(names_from = metric, values_from = amount) %>%
mutate(da = ifelse(AdjAllot > 0, Disbursements/AdjAllot, NA_real_),
expense_class = factor(expense_class, levels = c("1PS","2MOOE","6CO"), labels = ec_levels))
ggplot(absorp_ec, aes(year, da, color = expense_class, group = expense_class)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.8) +
geom_text(aes(label = scales::percent(da, accuracy = 1)), vjust = -1.0, size = 2.9, show.legend = FALSE, color = "grey20") +
scale_color_manual(values = ec_pal) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.05), breaks = seq(0, 1, 0.2)) +
scale_x_continuous(breaks = 2018:2025) +
labs(title = "Disbursement-to-Allotment by Expense Class, 2018–2025",
subtitle = "Personnel spending absorbs at ~98%; Capital Outlays barely move and are getting worse",
x = NULL, y = NULL) +
theme_doh() + guides(color = guide_legend(nrow = 1))
absorp_ec %>% mutate(da = round(da*100,0)) %>% select(expense_class, year, da) %>%
pivot_wider(names_from = year, values_from = da) %>%
rename(`D/A by expense class (%)` = expense_class) %>% kbl_clean(font = 12.5, na = "")
| D/A by expense class (%) | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 |
|---|---|---|---|---|---|---|---|---|
| Personnel Services (PS) | 91 | 98 | 98 | 98 | 98 | 98 | 98 | 98 |
| Maintenance & Other Op. Exp. (MOOE) | 44 | 54 | 51 | 56 | 53 | 70 | 64 | 57 |
| Capital Outlays (CO) | 28 | 14 | 29 | 37 | 28 | 27 | 23 | 19 |
The absorption problem is, at root, a Capital Outlay problem. CO disburses at just 14–37% of allotment across the period; PS at ~98%; MOOE in between (50–70%). When the aggregate D/A reads as “weak,” what is actually weak is the infrastructure pipeline. HFEP’s chronic 22–29% is therefore not an HFEP-specific failure — HFEP is almost entirely CO, and its number sits squarely on the systemwide CO baseline. Fixing HFEP means fixing capital-outlay execution in general. And CO disbursement is deteriorating: from 37% in 2021 to about 19% in 2025, the floor keeps dropping even as the budget grows.
The strongest absorbers are personnel-type and recurring-operations lines; the weakest are capital-heavy or newly-created lines. Both tables cover P/A/Ps with a 2025 allotment of at least ₱0.5B.
abs_2025 <- pap_year %>% filter(year == 2025, !is.na(AdjAllot), AdjAllot >= 5e8) %>%
mutate(`O/A` = Obligations/AdjAllot, `D/A` = Disbursements/AdjAllot, `Allotment (B)` = round(AdjAllot/1e9, 2))
Strongest absorbers, FY 2025 — ranked by obligation rate. Salary-type and hospital-operations lines obligate up front and disburse cleanly.
abs_2025 %>% arrange(desc(`O/A`)) %>% slice_head(n = 10) %>%
transmute(`P/A/P` = str_trunc(pap, 54), `Allotment (B)`,
`O/A` = scales::percent(`O/A`, accuracy = 1), `D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
kbl_clean(font = 13, align = "lrrr", na = "")
| P/A/P | Allotment (B) | O/A | D/A |
|---|---|---|---|
| Administration of Personnel Benefits | 11.95 | 100% | 97% |
| Regulation of Health Establishments and Products | 0.50 | 100% | 99% |
| National Health Workforce Support System (NHWSS) | 17.92 | 100% | 95% |
| Operation of Dangerous Drug Abuse Treatment and Reh… | 1.76 | 99% | 95% |
| Cancer Assistance Fund | 1.25 | 99% | 92% |
| Operations of DOH Hospitals in Metro Manila (MM) | 21.91 | 99% | 86% |
| Operations of DOH Regional Hospitals and Other Heal… | 73.71 | 97% | 87% |
| Foreign-Assisted Project: Philippine Multi-Sectoral… | 1.44 | 97% | 96% |
| Local Health Systems Development and Assistance | 0.66 | 94% | 76% |
| Operations of Blood Centers and National Voluntary … | 0.65 | 93% | 45% |
Weakest absorbers, FY 2025 — ranked by disbursement
rate. The new (2025) commodities lines under 3502 came in
near-zero in their first year; HFEP and the Quick Response Fund are
perennial.
abs_2025 %>% arrange(`D/A`) %>% slice_head(n = 10) %>%
transmute(`P/A/P` = str_trunc(pap, 54), `Allotment (B)`,
`O/A` = scales::percent(`O/A`, accuracy = 1), `D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
kbl_clean(font = 13, align = "lrrr", na = "")
| P/A/P | Allotment (B) | O/A | D/A |
|---|---|---|---|
| Nationally-procured Commodities for Family Planning… | 0.75 | 0% | 0% |
| Nationally-procured Commodities for Prevention and … | 3.48 | 13% | 0% |
| Nationally-procured Commodities for Family Health, … | 10.18 | 56% | 6% |
| Quick Response Fund | 0.50 | 50% | 6% |
| Health Information Technology | 2.30 | 10% | 8% |
| Nationally-procured Commodities for Prevention and … | 5.14 | 31% | 21% |
| Health Facilities Enhancement Program | 16.61 | 62% | 22% |
| Operations of Philippine Health Laboratory System | 0.75 | 60% | 26% |
| Supply Chain Management | 0.90 | 76% | 38% |
| Operations of Blood Centers and National Voluntary … | 0.65 | 93% | 45% |
The weakest-absorber list mixes a genuine structural problem with a
likely transition artefact. HFEP disbursing only 22% of
a ₱16.6B allotment is consistent with its long-running implementation
lag. But three of the new commodities programs under
PREXC 3502 disbursing near-zero in 2025 may reflect the
coding transition rather than a real procurement failure — first-year
lines often look catastrophic before they settle. The Quick
Response Fund disbursing 6% of its ₱500M ceiling is, by
contrast, a recurring story: emergency money that rarely flows on
schedule.
Every P/A/P with a 2025 allotment, all three ratios, sortable and searchable.
abs_full <- pap_year %>% filter(year == 2025, !is.na(AdjAllot), AdjAllot > 0) %>%
transmute(`P/A/P` = pap, `Allotment (B)` = AdjAllot/1e9, `Obligations (B)` = Obligations/1e9,
`Disbursements (B)` = Disbursements/1e9, `O/A` = Obligations/AdjAllot,
`D/O` = ifelse(Obligations>0, Disbursements/Obligations, NA_real_), `D/A` = Disbursements/AdjAllot) %>%
arrange(`D/A`)
dt_table(abs_full, page = 15,
money_cols = c("Allotment (B)","Obligations (B)","Disbursements (B)"),
pct_cols = c("O/A","D/O","D/A"))
Six heavyweight programs, each showing enacted budget, allotment, and disbursements together. Where the lines sit on top of one another, execution is clean; where disbursements fall away, money is released but unspent.
trend_paps <- c(
"Operations of DOH Regional Hospitals and Other Health Facilities",
MAIFIP_LAB,
"Operations of DOH Hospitals in Metro Manila (MM)",
"National Health Workforce Support System (NHWSS)",
"Health Facilities Enhancement Program",
"Administration of Personnel Benefits")
trend_dat <- pap_year %>% filter(pap %in% trend_paps) %>%
select(pap, year, GAA, AdjAllot, Disbursements) %>%
pivot_longer(c(GAA, AdjAllot, Disbursements), names_to = "metric", values_to = "amount") %>%
mutate(metric = factor(metric, levels = c("GAA","AdjAllot","Disbursements"),
labels = c("GAA (enacted)","Adj. Allotment","Disbursements")),
pap = factor(pap, levels = trend_paps,
labels = c("Regional Hospitals","MAIFIP","MM Hospitals","NHWSS",
"Health Facilities Enhancement Program","Administration of Personnel Benefits")))
trend_pal <- c("GAA (enacted)" = "#54278F","Adj. Allotment" = "#08519C","Disbursements" = "#31A354")
ggplot(trend_dat, aes(year, amount, color = metric, group = metric)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.5) +
facet_wrap(~ pap, ncol = 3, scales = "free_y",
labeller = label_wrap_gen(width = 24)) + expand_limits(y = 0) +
scale_color_manual(values = trend_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(4)) +
scale_x_continuous(breaks = c(2018, 2022, 2026)) +
labs(title = "How the six largest health programs have evolved (2018–2026)",
subtitle = "GAA vs. allotment vs. disbursements — the absorption gap is widest for HFEP and MAIFIP",
x = NULL, y = NULL) +
theme_doh() + guides(color = guide_legend(nrow = 1))
The two hospital lines (Regional and MM) are steady workhorses — budget, allotment, and disbursement move almost in lockstep, the 2025 Regional Hospitals GAA of ₱75.6B disbursing at about 92%. NHWSS, the frontline-health-workforce line (formerly HRH Deployment), is the standout among the large programs: it scaled from ₱9.6B (2018) to ₱23.4B (2026) while absorbing cleanly throughout (D/A 87–98%) — growth without an execution lag. MAIFIP shows runaway GAA growth with disbursement running well below, and HFEP is the flat disbursement curve beneath a volatile budget. Administration of Personnel Benefits is a straightforward payroll line, near-fully disbursed every year.
The Health Facilities Enhancement Program — DOH-OSEC’s main infrastructure line — is the deepest structural absorption issue in the portfolio. It builds and upgrades health facilities, and it has never managed to spend what it is given.
hfep <- pap_year %>% filter(pap == "Health Facilities Enhancement Program") %>%
select(year, NEP, GAA, AdjAllot, Obligations, Disbursements) %>%
pivot_longer(-year, names_to = "metric", values_to = "amount") %>%
mutate(metric = factor(metric, levels = c("NEP","GAA","AdjAllot","Obligations","Disbursements"),
labels = c("NEP (proposed)","GAA (enacted)","Adj. Allotment","Obligations","Disbursements")))
ggplot(hfep, aes(year, amount, color = metric, group = metric)) +
geom_line(linewidth = 0.9) + geom_point(size = 1.8) +
scale_color_manual(values = exec_pal) +
scale_y_continuous(labels = php_b_axis, breaks = pretty_breaks(6), limits = c(0, NA), expand = expansion(mult = c(0, .05))) +
scale_x_continuous(breaks = seq(2018, 2026, 2)) +
labs(title = "Health Facilities Enhancement Program (HFEP), 2018–2026",
subtitle = "Allotments are downward-adjusted from GAA; disbursements barely move",
x = NULL, y = NULL) +
theme_doh() + guides(color = guide_legend(nrow = 1))
pap_year %>% filter(pap == "Health Facilities Enhancement Program", year %in% 2018:2025) %>%
transmute(FY = year, `NEP (B)` = round(NEP/1e9,1), `GAA (B)` = round(GAA/1e9,1),
`Allotment (B)` = round(AdjAllot/1e9,1), `Disbursed (B)` = round(Disbursements/1e9,1),
`D/A` = scales::percent(Disbursements/AdjAllot, accuracy = 1)) %>%
kbl_clean(font = 14, align = "rrrrrr", na = "")
| FY | NEP (B) | GAA (B) | Allotment (B) | Disbursed (B) | D/A |
|---|---|---|---|---|---|
| 2018 | 29.0 | 30.3 | 30.3 | 8.4 | 28% |
| 2019 | 0.0 | 15.9 | 15.6 | 2.0 | 13% |
| 2020 | 5.9 | 8.4 | 8.3 | 2.7 | 32% |
| 2021 | 4.8 | 7.8 | 7.8 | 2.5 | 32% |
| 2022 | 19.6 | 23.1 | 23.1 | 6.7 | 29% |
| 2023 | 23.0 | 26.8 | 26.8 | 7.7 | 29% |
| 2024 | 23.0 | 28.6 | 18.1 | 4.2 | 23% |
| 2025 | 23.0 | 35.4 | 16.6 | 3.7 | 22% |
Three things stand out. First, DBM has been cutting HFEP releases: the GAA reached ₱35.4B in 2025 but only ₱16.6B was actually allotted — the Adjusted Allotment ran ₱10–19B below the enacted budget in 2024 and 2025. Whatever the absorption story, DBM is already pricing it in. Second, the 2026 GAA fell to ₱22.3B (from ₱35.4B), the first major reversal since HFEP’s 2022 recovery, suggesting Congress too is acknowledging the ceiling. Third, the ceiling is structural: D/A has never exceeded 32% in any year on record, and cumulative unspent allotment across 2018–2025 is roughly ₱109B — close to four full years of average HFEP allotment. Procurement and NGA–LGU coordination are the usual diagnoses; the practical question is which specific reform would actually move the number.
A set of public-health programs with persistently low obligation
rates. Several lines stop in 2024 because the 2025 reorganization
re-coded them (3103 → 3501/3502),
which is itself part of the story — reorganizations interrupt execution
histories.
low_paps <- c("Health Information Technology","Quick Response Fund","Health Promotion",
"Family Health, Immunization, Nutrition and Responsible Parenting",
"Prevention and Control of Communicable Diseases","Prevention and Control of Non-Communicable Diseases")
low_dat <- pap_year %>% filter(pap %in% low_paps) %>%
mutate(oa = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Obligations/AdjAllot, NA_real_),
pap = factor(pap, levels = low_paps,
labels = c("Health Information Technology","Quick Response Fund","Health Promotion",
"FH, Imm, Nutrition & Resp. Parenting","Prev. & Control of Communicable Diseases",
"Prev. & Control of Non-Communicable Diseases"))) %>%
select(pap, year, oa) %>% tidyr::complete(year = 2018:2025, pap)
ggplot(low_dat, aes(year, oa, group = 1)) +
geom_hline(yintercept = 1, linetype = "dotted", color = "grey60") +
geom_line(linewidth = 0.9, color = "#E6550D") + geom_point(size = 1.6, color = "#E6550D") +
geom_text(aes(label = scales::percent(oa, accuracy = 1)), vjust = -0.9, size = 2.6, color = "grey20") +
facet_wrap(~ pap, ncol = 3, labeller = label_wrap_gen(width = 24)) +
scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.15), breaks = seq(0, 1, 0.25)) +
scale_x_continuous(breaks = c(2018, 2021, 2023, 2025)) +
labs(title = "Obligations-to-Allotment ratios: chronic under-absorbers (2018–2025)",
subtitle = "Several lines disappeared in 2025 due to the PREXC reorganization (3103 → 3501/3502)",
x = NULL, y = NULL) +
theme_doh() + theme(legend.position = "none")
These are the public-health and emergency-response lines — health promotion, disease control, the Quick Response Fund, health IT — where even the obligation rate (a looser test than disbursement) runs well below full. They are individually small but collectively define the agency’s public-health-delivery capacity, and they are precisely the programs the 2025 reorganization was meant to rationalize.
The top 30 P/A/Ps by 2026 GAA, with the 2026 NEP and GAA, the prior-year (2025) enacted budget, and the most recent (2025) disbursement-to-allotment ratio as an execution indicator. The full unabridged list is in the ranking section above.
ref <- pap_year %>% filter(year == 2026, !is.na(GAA), GAA > 0) %>%
arrange(desc(GAA)) %>% slice_head(n = 30) %>%
transmute(pap, `NEP 2026 (B)` = NEP/1e9, `GAA 2026 (B)` = GAA/1e9)
ctx_2025 <- pap_year %>% filter(year == 2025) %>%
transmute(pap, `GAA 2025 (B)` = GAA/1e9,
`D/A 2025` = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Disbursements/AdjAllot, NA_real_))
ref %>% left_join(ctx_2025, by = "pap") %>% rename(`P/A/P` = pap) %>%
dt_table(page = 15, money_cols = c("NEP 2026 (B)","GAA 2026 (B)","GAA 2025 (B)"), pct_cols = "D/A 2025")
2026 execution data is not yet available; the 2025 D/A column indicates how each line has most recently absorbed.
Underlying data: DBM-published budget and execution data for the DOH Office of the Secretary (Current New Appropriations only), FY 2018–2026. Execution measures (Allotments, Obligations, Disbursements) cover FY 2018–2025. Prepared as the long-form companion to the DOH-OSEC budget briefing.