Overview

This document follows the budget of the Department of Education – Office of the Secretary (DepEd-OSEC) across ten fiscal years, from the FY 2018 enacted budget to the FY 2027 proposal, and traces each peso through the four stages of the public-expenditure cycle: proposed (NEP), enacted (GAA), released (allotment), committed (obligation), and finally paid out (disbursement).

It is the long-form companion to the DepEd-OSEC briefing deck. Where the deck compresses each point to a single slide, this version keeps the full reasoning and adds reference tables — most of them sortable and searchable — so that a reader can interrogate the figures directly rather than take the narrative on trust. Every table can be copied or exported to CSV from its toolbar.

The story has one organizing tension. DepEd-OSEC is, in budget terms, a payroll organization: roughly two-thirds to four-fifths of its money is teacher and staff salaries, and salaries are spent with near-perfect reliability. That makes the agency’s headline absorption look excellent. But it also means the headline number tells you almost nothing about the programs that actually deliver classrooms, textbooks, equipment, and subsidies — and those programs are where execution repeatedly breaks down. Most of what follows is an attempt to look past the salary block at the discretionary tail underneath it.

1 Executive summary

The FY 2027 proposal (NEP) is ₱914B for DepEd-OSEC — up about ₱41B (+5%) on the FY 2026 proposal and the largest yet, though it still sits ₱44B below the Congress-augmented 2026 enacted level (₱959B). The increase is concentrated in running schools: Operation of Schools — Elementary (+₱32B), Junior High (+₱18B), and Senior High (+₱9B), plus the teachers’ cash allowance (+₱7.5B). The student subsidies were reclassified, not cut: the Senior High Voucher (₱26.5B) and Educational Service Contracting (₱12.4B) are folded into a single new Government Assistance and Subsidies line (₱38.1B), roughly budget-neutral but harder to track by component. Several quality-and-access inputs are trimmed in the proposal — Computerization (−₱10.7B), New School Personnel Positions (−₱10.6B), Textbooks (−₱4.7B), and resilient-school infrastructure (−₱7.2B).

The DepEd-OSEC budget has grown about 1.7× in nominal terms, from a ₱552B enacted budget in 2018 to a proposed ₱959B in the 2026 GAA. Growth has been steady rather than smooth, with the steepest single-year jumps in 2023 and 2026.

In structure this is a teacher-salary organization. The three “Operation of Schools” lines — Elementary, Junior High, and Senior High — together account for 65–78% of the OSEC budget in every year, and Personnel Services alone is 64–80% of every year’s GAA. Operation of Schools – Elementary, by itself, is ₱358B in the 2026 GAA: more than a third of the entire office.

That structure is why headline absorption looks strong. Obligations run 93–97% of allotments and disbursements 86–92% — but this is carried almost entirely by Personnel Services, which disburses at 97–99% like clockwork. Strip the salaries away and a very different picture emerges.

The non-salary tail absorbs far worse. Textbooks and Other Instructional Materials disbursed just 2–17% of its allotment in every year on record; Basic Education Facilities, the agency’s capital-outlay bottleneck, has swung between 16% and 54% with no clear improvement. The GASTPE demand-side subsidies collapsed after 2022 — the Senior High School Voucher fell from near-full disbursement to 28% by 2025, and Educational Service Contracting from ~80% to the mid-30s.

Two structural shifts stand out at the top of the budget. Capital Outlay was squeezed from 22% of the budget in 2018 to 3–5% in 2021–2023, then restored sharply to about ₱100B (10%) in the 2026 GAA. And FY 2026 carries a record Congressional augmentation: the ₱873B NEP was raised to a ₱959B GAA, an ₱86B add-on after years in which the enacted budget barely departed from the Executive’s proposal.

The recurring policy question this raises: Congress channels its largest additions into exactly the procurement-heavy lines — facilities, textbooks, feeding — that already struggle most to disburse what they have. Capacity to spend, not willingness to appropriate, is the binding constraint.

2 A note on the data

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, and Disbursements — is available for FY 2018–2025; FY 2026 reflects the proposed/enacted budget only, with no execution data yet.

Scope. The main analysis is DepEd Office of the Secretary only; the attached agencies (the National Museum, the ECCD Council, the National Book Development Board, and others) are summarised in a short attached-agencies section at the end. Figures are Current New Appropriations only — they exclude Continuing and Automatic Appropriations and Special Purpose Fund transfers. All amounts are in nominal pesos; no inflation adjustment is applied.

P/A/P consolidation. Two programs appear under two or three slightly different P/A/P labels across the years: the Educational Service Contracting (ESC) program and the Senior High School Voucher program. Each is reported here as a single continuous line so its trajectory can be read without artificial breaks.

Absorptive-capacity denominator. Unless stated otherwise, absorption ratios use Adjusted Allotments as the denominator — the closest available proxy for what the agency was actually cleared to spend in a given year.

Key terms. NEP (National Expenditure Program) is the Executive’s proposed budget; GAA (General Appropriations Act) is the enacted budget. Obligations are spending commitments (contracts signed, orders placed); Disbursements are cash actually paid out. The three ratios used throughout are O/A (Obligations ÷ Allotment), D/O (Disbursements ÷ Obligations), and D/A (Disbursements ÷ Allotment, the end-to-end measure).

3 The aggregate budget

3.1 The budget keeps growing

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 = "DepEd-OSEC budget, NEP through Disbursements (FY 2018–2027)",
       subtitle = "The enacted budget tracks the proposal closely — until a record 2026 augmentation; the FY 2027 NEP proposes ~PHP 914B",
       x = NULL, y = NULL,
       caption = "FY 2027 is the NEP (proposed) only; FY 2026 reflects NEP/GAA only; execution runs through 2025.") +
  theme_deped() + guides(color = guide_legend(nrow = 1))

Three features of this chart organize the rest of the document. First, the NEP and GAA lines sit almost on top of each other for eight of the nine years — DepEd is rarely a target of large Congressional revision — and then visibly separate in 2026. Second, the allotment, obligation, and disbursement lines track below the enacted budget in a stable band, and the disbursement line pulls away slightly in 2024–2025, hinting at a widening execution gap. Third, the overall slope is firmly upward: this is a growing budget in every multi-year stretch.

The table below gives the underlying figures for every year, in billions of pesos.

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 = 0, format.args = list(big.mark = ","), na = "")
PHP B 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
NEP 585 498 518 568 589 666 712 746 873 914
GAA 553 500 520 556 591 676 715 734 959
Adj. Allotment 477 530 517 607 642 720 769 802
Obligations 454 503 501 590 612 682 714 756
Disbursements 426 472 466 552 593 647 660 694

3.2 Year-on-year growth

Reading the levels above as growth rates makes the budget’s rhythm clearer. The enacted budget actually contracted in 2019 (a post-election re-enactment year), then expanded every year after, with the two largest jumps being 2023 (+14%) and the 2026 proposal (+31% over the 2025 GAA, the bulk of it from the Congressional add-on).

growth <- totals_by_year %>%
  filter(metric == "GAA") %>% arrange(year) %>%
  mutate(`GAA (B)` = total/1e9,
         `Δ vs prior yr (B)` = (total - lag(total))/1e9,
         `Growth %` = (total/lag(total) - 1)) %>%
  select(year, `GAA (B)`, `Δ vs prior yr (B)`, `Growth %`)

growth %>%
  mutate(`GAA (B)` = round(`GAA (B)`,1),
         `Δ vs prior yr (B)` = round(`Δ vs prior yr (B)`,1),
         `Growth %` = scales::percent(`Growth %`, accuracy = 0.1)) %>%
  kbl_clean(font = 13, align = "rrrr", na = "")
year GAA (B) Δ vs prior yr (B) Growth %
2018 552.5
2019 500.3 -52.3 -9.5%
2020 520.3 20.0 4.0%
2021 556.4 36.1 6.9%
2022 591.2 34.8 6.3%
2023 676.1 85.0 14.4%
2024 715.3 39.2 5.8%
2025 734.2 18.9 2.6%
2026 958.7 224.5 30.6%
2027

Growth is measured on the enacted GAA. The 2026 figure compares the proposed/enacted 2026 budget to the 2025 GAA.

4 Where the money goes

4.1 Composition by PREXC program

DepEd-OSEC’s budget is organized into seven PREXC programs. The chart shows how the enacted budget divides among them each year; the table that follows gives the exact peso amounts and each program’s share of the total.

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 PREXC program, 2018–2026",
       subtitle = "Support to Schools and Learners is by far the largest program; Basic Education Inputs is second",
       x = NULL, y = NULL) +
  theme_deped() + guides(fill = guide_legend(nrow = 4, byrow = TRUE))

The Support to Schools and Learners Program — which houses the three Operation of Schools lines — dwarfs the others; it is the salary engine of the department. The Basic Education Inputs Program (textbooks, facilities, equipment, computerization) is a distant but important second, and it is here that most of the absorption problems documented later in this report live. The smaller programs — policy development, inclusive education, human-resource development — are modest in budget terms but not in mandate.

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(`Program (PHP B)` = category),
          font = 12, digits = 1, format.args = list(big.mark=","), na = "") %>%
  add_header_above(c(" " = 1, "General Appropriations Act, by year (PHP billions)" = ncol(comp_amt)-1))
General Appropriations Act, by year (PHP billions)
Program (PHP B) 2018 2019 2020 2021 2022 2023 2024 2025 2026
Basic Education Inputs Program 169.1 77.7 62.8 40.2 45.2 66.5 92.2 87.5 174.7
Education Human Resource Development Program 3.4 2.0 2.0 1.9 1.9 2.1 4.1 2.8 5.1
Education Policy Development Program 7.2 7.9 7.9 7.9 8.2 13.8 13.9 12.6 16.0
General Administration and Support 26.2 13.9 8.1 14.4 14.7 21.8 22.1 19.9 29.2
Inclusive Education Program 1.3 1.2 1.2 17.5 16.3 5.4 6.0 6.1 6.8
Support to Operations 3.4 3.6 3.7 3.2 3.4 5.6 6.5 5.0 10.5
Support to Schools and Learners Program 342.0 393.9 434.6 471.2 501.5 560.9 570.4 600.3 716.4

Share of each year’s total budget for the same programs:

comp_pct <- comp_tbl %>%
  mutate(share = round(share*100,1)) %>%
  select(category, year, share) %>%
  pivot_wider(names_from = year, values_from = share)
kbl_clean(comp_pct %>% rename(`Program (% of GAA)` = category),
          font = 12, digits = 1, na = "")
Program (% of GAA) 2018 2019 2020 2021 2022 2023 2024 2025 2026
Basic Education Inputs Program 30.6 15.5 12.1 7.2 7.6 9.8 12.9 11.9 18.2
Education Human Resource Development Program 0.6 0.4 0.4 0.3 0.3 0.3 0.6 0.4 0.5
Education Policy Development Program 1.3 1.6 1.5 1.4 1.4 2.0 1.9 1.7 1.7
General Administration and Support 4.7 2.8 1.6 2.6 2.5 3.2 3.1 2.7 3.0
Inclusive Education Program 0.2 0.2 0.2 3.1 2.8 0.8 0.8 0.8 0.7
Support to Operations 0.6 0.7 0.7 0.6 0.6 0.8 0.9 0.7 1.1
Support to Schools and Learners Program 61.9 78.7 83.5 84.7 84.8 82.9 79.7 81.8 74.7

4.2 Composition by expense class

The same budget, cut a different way — by what the money buys rather than which program it sits in. Three expense classes matter for DepEd-OSEC: Personnel Services (PS, salaries and benefits), Maintenance and Other Operating Expenses (MOOE, the running costs of programs), and Capital Outlays (CO, infrastructure and equipment).

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 = "Personnel Services is 64–80% of the budget every year; Capital Outlays was squeezed, then restored in 2026",
       x = NULL, y = NULL) +
  theme_deped() + guides(fill = guide_legend(nrow = 1))

The PS block is the dominant feature and it grows roughly in line with the headcount of the school system. The Capital Outlay story is the most dynamic: CO was a substantial 22% of the 2018 budget, was compressed to the low single digits in 2021–2023 as fiscal space tightened during and after the pandemic, and is sharply restored in the 2026 GAA. The share table makes the swing explicit.

ec_share <- comp_ec %>%
  group_by(year) %>% mutate(share = amount/sum(amount)) %>% ungroup()

ec_pct <- ec_share %>% mutate(share = round(share*100,1)) %>%
  select(expense_class, year, share) %>%
  pivot_wider(names_from = year, values_from = share)
kbl_clean(ec_pct %>% 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) 63.9 74.8 74.1 78.7 80.0 75.8 73.2 74.1 68.0
Maintenance & Other Op. Exp. (MOOE) 13.9 16.4 18.3 17.8 16.6 19.0 20.1 21.3 21.6
Capital Outlays (CO) 22.2 8.8 7.6 3.5 3.4 5.2 6.7 4.6 10.4

That restoration is a setup for a question this report returns to repeatedly: Capital Outlay has historically been DepEd-OSEC’s weakest-absorbing expense class. Putting ₱100B of CO back into the budget only delivers classrooms if the agency can disburse it — and the recent record there is poor.

4.3 The ten largest P/A/Ps (FY 2027 NEP, proposed)

At the line-item level, concentration is extreme. The ten largest P/A/Ps in the FY 2027 proposal (NEP), charted below, account for the overwhelming majority of the office’s budget.

top10 <- pap_year %>%
  filter(year == 2027, !is.na(NEP)) %>%
  arrange(desc(NEP)) %>% slice_head(n = 10) %>%
  mutate(pap = factor(pap, levels = rev(pap)))

ggplot(top10, 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, 42)) +
  scale_y_continuous(labels = php_b_axis, expand = expansion(mult = c(0, .20)), limits = c(0, NA)) +
  labs(title = "Top 10 P/A/Ps by FY 2027 NEP (proposed)",
       subtitle = "Operation of Schools – Elementary alone is PHP 390B — about 43% of the proposed OSEC budget",
       x = NULL, y = NULL) +
  theme_deped() +
  theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))

Full P/A/P ranking, FY 2027 proposal (interactive)

The chart shows ten lines; the office has many more. The table below ranks every P/A/P by its FY 2027 proposal (NEP), alongside the FY 2026 proposal and enacted budget, so the full distribution — and the long tail of small programs — is available for inspection. Lines that existed only in one year (for example the reclassified subsidy lines) show a blank where they have no figure. Sort by any column, search by name, or export the whole thing.

all_paps <- 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)
all_paps <- all_paps %>% full_join(nep_gaa_26, by = "P/A/P") %>%
  arrange(desc(`NEP 2027 (B)`))

dt_table(all_paps, page = 15,
         money_cols = c("NEP 2027 (B)","NEP 2026 (B)","GAA 2026 (B)"))

4.4 What the FY 2027 proposal changes

Comparing the two proposals — the FY 2026 NEP against the FY 2027 NEP — isolates what the Executive itself chose to change, before Congress acts. The chart excludes the reclassified subsidy lines: in FY 2027 the Senior High Voucher (₱26.5B) and Educational Service Contracting (₱12.4B) are consolidated into a single “Government Assistance and Subsidies” line (₱38.1B) — a roughly budget-neutral relabelling, not a cut, that would otherwise swamp the chart with two large false “reductions” and one false “increase.”

excl_reclass <- c("GAS - Educational Service Contracting (ESC) for Private JHS",
                  "GAS - Senior High School Voucher Program",
                  "Government Assistance and Subsidies")
nep_change <- pap_year %>%
  filter(year %in% c(2026, 2027), !pap %in% excl_reclass) %>%
  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.5)
ups   <- nep_change %>% filter(change > 0) %>% arrange(desc(change)) %>% slice_head(n = 7)
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, 44)) +
  scale_y_continuous(labels = function(v) paste0(peso, v, "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, subsidy reclassification excluded",
       x = NULL, y = NULL) +
  theme_deped() +
  theme(panel.grid.major.y = element_blank(),
        panel.grid.major.x = element_line(color = "grey85"),
        legend.position = "none")

The proposal leans into running schools: Operation of Schools — Elementary (+₱32B), Junior High (+₱18B), and Senior High (+₱9B), together with the teachers’ cash allowance (+₱7.5B), account for almost all of the net increase. The reductions fall on quality-and-access inputs — the Computerization Program (−₱10.7B), New School Personnel Positions (−₱10.6B, i.e. fewer new teacher items), resilient-school infrastructure (−₱7.2B), and Textbooks and other instructional materials (−₱4.7B). It is a proposal that funds operating existing schools more generously while trimming the equipment, construction, and new-hiring lines — a within-proposal tilt worth watching, since several of those trimmed lines are ones Congress has restored before.

4.5 Operation of Schools dominates

Collapsing the budget to just the three school-operations lines against everything else shows how lopsided the distribution is.

oos <- c("Operation of Schools - Elementary (Kinder to Grade 6)",
         "Operation of Schools - Junior High School (Grade 7 to Grade 10)",
         "Operation of Schools - Senior High School (Grade 11 to Grade 12)")
share <- df_long %>%
  filter(metric == "GAA", year <= 2026, !is.na(amount)) %>%
  mutate(grp = case_when(
    pap == oos[1] ~ "Operation of Schools - Elementary",
    pap == oos[2] ~ "Operation of Schools - JHS",
    pap == oos[3] ~ "Operation of Schools - SHS",
    TRUE          ~ "All other P/A/Ps")) %>%
  group_by(year, grp) %>% summarise(amount = sum(amount, na.rm = TRUE), .groups = "drop") %>%
  mutate(grp = factor(grp, levels = c("Operation of Schools - Elementary","Operation of Schools - JHS",
                                      "Operation of Schools - SHS","All other P/A/Ps")))
school_pal <- c("Operation of Schools - Elementary" = "#08519C","Operation of Schools - JHS" = "#3182BD",
                "Operation of Schools - SHS" = "#9ECAE1","All other P/A/Ps" = "#D9D9D9")

ggplot(share, aes(year, amount, fill = grp)) +
  geom_col(width = 0.75, color = "white", linewidth = 0.2) +
  scale_fill_manual(values = school_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 = "Operation of Schools vs. everything else, FY 2018–2026 GAA",
       subtitle = "The three school-level lines together are 65–78% of the OSEC budget",
       x = NULL, y = NULL) +
  theme_deped() + guides(fill = guide_legend(nrow = 2, byrow = TRUE))

Why this concentration matters, in four points:

  • The three Operation of Schools P/A/Ps make up 65–78% of the entire OSEC budget, and Operation of Schools – Elementary alone is ₱358B in the 2026 GAA.
  • These lines are almost pure Personnel Services — teacher and non-teaching staff salaries — and they are obligated and paid like clockwork, disbursing at 98–99% of allotment.
  • This is precisely why the agency’s headline absorption looks excellent: a budget that is two-thirds salaries will always post a high aggregate disbursement rate, regardless of how the rest is performing.
  • The corollary is the analytical heart of this report: everything interesting — and everything problematic — is in the other quarter-to-third of the budget: facilities, materials, equipment, subsidies. For anyone focused on learning outcomes and service delivery, that non-salary tail is where attention belongs.

5 Congressional action: NEP → GAA

DepEd is rarely heavily augmented. In most years the enacted GAA differs from the Executive’s NEP by under 2%. The chart below is therefore cumulative over all nine budget cycles, isolating where Congress has consistently added to — or trimmed from — the President’s proposal. Only movements of at least ₱0.5B are shown.

aug <- pap_year %>%
  filter(year <= 2026) %>%
  group_by(pap) %>%
  summarise(nep = sum(NEP, na.rm = TRUE), gaa = sum(GAA, na.rm = TRUE), .groups = "drop") %>%
  mutate(change = gaa - nep) %>% filter(abs(change) >= 5e8)

aug_plot <- bind_rows(
  aug %>% arrange(desc(change)) %>% slice_head(n = 8),
  aug %>% arrange(change) %>% slice_head(n = 8)) %>%
  distinct() %>%
  mutate(direction = ifelse(change >= 0, "Net increase (GAA > NEP)", "Net decrease (GAA < NEP)"),
         hj = ifelse(change >= 0, -0.12, 1.12),
         pap = factor(pap, levels = pap[order(change)]))

ggplot(aug_plot, aes(pap, change/1e9, fill = direction)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = sprintf("%+.1fB", change/1e9), hjust = hj), size = 2.9, color = "grey20") +
  coord_flip() +
  scale_fill_manual(values = c("Net increase (GAA > NEP)" = "#1B9E77", "Net decrease (GAA < NEP)" = "#D95F02")) +
  scale_x_discrete(labels = function(x) str_trunc(x, 44)) +
  scale_y_continuous(labels = function(v) paste0(peso, v, "B"), expand = expansion(mult = c(0.20, 0.20))) +
  labs(title = "Cumulative NEP-to-GAA change by P/A/P, 2018–2026",
       subtitle = "Congress adds most to Basic Education Facilities; trims most from Computerization",
       x = NULL, y = NULL) +
  theme_deped() +
  theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85")) +
  guides(fill = guide_legend(nrow = 1))

The pattern carries a built-in tension. The lines Congress augments most — Basic Education Facilities, Textbooks, School-Based Feeding — are among the weakest absorbers in the entire portfolio (documented in the next section). Extra money is being routed, year after year, into precisely the programs least able to spend what they already have. Augmentation is an act of appropriation; it does nothing on its own to fix the downstream procurement and liquidation bottlenecks that keep these lines from disbursing.

The full cumulative table below lists every P/A/P with a material (≥₱0.5B) net change over the nine years, so the complete pattern of Congressional preference — not just the sixteen largest movements — is available.

aug_full <- aug %>%
  transmute(`P/A/P` = pap,
            `Σ NEP 2018–26 (B)` = nep/1e9,
            `Σ GAA 2018–26 (B)` = gaa/1e9,
            `Cumulative Δ (B)` = change/1e9) %>%
  arrange(desc(`Cumulative Δ (B)`))
dt_table(aug_full, page = 10,
         money_cols = c("Σ NEP 2018–26 (B)","Σ GAA 2018–26 (B)","Cumulative Δ (B)"))

6 Absorptive capacity

6.1 At the aggregate

At the whole-office level, DepEd-OSEC looks like a model absorber. All three execution ratios hold within a tight 86–97% band across 2018–2025.

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) +
  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 = "DepEd-OSEC absorptive capacity, 2018–2025",
       subtitle = "At the aggregate, DepEd is a strong absorber — all three ratios hold in a tight 86–97% band",
       x = NULL, y = NULL) +
  theme_deped() + guides(color = guide_legend(nrow = 1))

absorp_total %>%
  transmute(Year = year,
            `Adj. 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 Adj. Allotment (B) Obligations (B) Disbursements (B) O/A D/O D/A
2018 477.0 453.8 426.0 95% 94% 89%
2019 529.9 503.3 472.2 95% 94% 89%
2020 517.0 501.0 466.0 97% 93% 90%
2021 607.5 590.0 552.2 97% 94% 91%
2022 642.4 611.9 592.9 95% 97% 92%
2023 719.9 682.3 647.4 95% 95% 90%
2024 768.6 714.1 660.1 93% 92% 86%
2025 802.0 755.7 693.9 94% 92% 87%

6.2 By expense class

The aggregate is a weighted blend, and decomposing it by expense class is where the headline number falls apart. The end-to-end disbursement-to-allotment ratio is plotted separately for each expense class below.

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 Services absorbs at ~98%; MOOE is uneven; Capital Outlays swings wildly and mostly low",
       x = NULL, y = NULL) +
  theme_deped() + 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) 98 98 97 97 97 99 98 97
Maintenance & Other Op. Exp. (MOOE) 75 76 73 74 80 70 53 55
Capital Outlays (CO) 32 30 33 40 14 9 27 54

The absorption paradox

At the aggregate, DepEd-OSEC looks like a model absorber: disbursement-to-allotment holds at 86–92% every year, and taken alone that number suggests budget execution is not a problem. But that average is a weighted blend of a near-perfect Personnel Services block (98–99%) and a much weaker non-salary tail. MOOE disburses at 53–80% and has weakened sharply since 2023; Capital Outlay swings between roughly 9% and 54% and is low in most years. The programs that actually deliver classrooms, textbooks, equipment, and subsidies — the discretionary, procurement-heavy lines — are exactly where appropriated money piles up undisbursed. The headline figure is therefore misleading for service delivery: because salaries dominate, the agency-wide absorption rate hides the very execution failures that matter most for learners.

6.3 Strongest and weakest absorbers (FY 2025)

To make the paradox concrete, the next two tables rank P/A/Ps with a 2025 allotment of at least ₱1B by their end-to-end D/A ratio. The strongest absorbers are salary-driven school-operations lines and a handful of small, well-defined programs; the weakest are procurement- and subsidy-heavy.

abs_2025 <- pap_year %>%
  filter(year == 2025, !is.na(AdjAllot), AdjAllot >= 1e9) %>%
  mutate(`O/A` = Obligations/AdjAllot, `D/O` = Disbursements/Obligations,
         `D/A` = Disbursements/AdjAllot, `Allotment (B)` = round(AdjAllot/1e9, 1))

Strongest absorbers, FY 2025 — disbursement at or near 100% is the norm where spending is payroll.

abs_2025 %>% arrange(desc(`D/A`)) %>% slice_head(n = 8) %>%
  transmute(`P/A/P` = str_trunc(pap, 52), `Allotment (B)`,
            `O/A` = scales::percent(`O/A`, accuracy = 1),
            `D/O` = scales::percent(`D/O`, accuracy = 1),
            `D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
  kbl_clean(font = 13, align = "lrrrr", na = "")
P/A/P Allotment (B) O/A D/O D/A
Connectivity Enhancement Program for e-Learning i… 1.5 100% 100% 100%
Operation of Schools - Junior High School (Grade … 184.0 99% 99% 99%
Curriculum Programs, Learning Management Models, … 6.8 100% 99% 99%
Operation of Schools - Elementary (Kinder to Grad… 331.2 100% 98% 98%
Operation of Schools - Senior High School (Grade … 58.9 99% 99% 98%
Policy and Research Program 2.2 99% 98% 97%
Joint Delivery Voucher for Senior High School Tec… 1.5 94% 98% 91%
Quick Response Fund 2.6 99% 92% 91%

Weakest absorbers, FY 2025 — instructional materials, equipment, facilities, and the demand-side voucher/ESC lines. Textbooks disbursed 14% of a ₱17B allotment.

abs_2025 %>% arrange(`D/A`) %>% slice_head(n = 8) %>%
  transmute(`P/A/P` = str_trunc(pap, 52), `Allotment (B)`,
            `O/A` = scales::percent(`O/A`, accuracy = 1),
            `D/O` = scales::percent(`D/O`, accuracy = 1),
            `D/A` = scales::percent(`D/A`, accuracy = 1)) %>%
  kbl_clean(font = 13, align = "lrrrr", na = "")
P/A/P Allotment (B) O/A D/O D/A
Learning Tools and Equipment 4.4 49% 21% 10%
Textbooks and Other Instructional Materials 17.2 58% 24% 14%
National Assessment Systems for Basic Education 1.8 68% 34% 23%
Basic Education Facilities 8.9 64% 43% 27%
GAS - Senior High School Voucher Program 31.5 55% 52% 28%
GAS - Educational Service Contracting (ESC) for P… 16.4 65% 54% 35%
Flexible Learning Options (ADM/ALS/EiE) 5.9 86% 41% 35%
School-Based Feeding Program (SBFP) 14.3 91% 53% 48%

Full absorption table, FY 2025 (interactive)

Both curated tables above are slices of the same underlying data. The interactive table below contains every P/A/P with a 2025 allotment, with all three ratios, sortable and searchable — the complete absorption picture rather than the top and bottom eight. Sort ascending on D/A to see the chronic problem lines; sort descending on Allotment to see where the largest sums sit.

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"))

7 Program deep-dives

7.1 Trajectories of the largest programs

Six of the most consequential programs are tracked below, each showing the enacted budget, the adjusted allotment, and disbursements together. Where the three lines sit on top of one another, execution is clean; where the disbursement line falls away from the allotment, money is being appropriated and released but not paid out.

trend_paps <- c(
  "Operation of Schools - Elementary (Kinder to Grade 6)",
  "Operation of Schools - Junior High School (Grade 7 to Grade 10)",
  "Operation of Schools - Senior High School (Grade 11 to Grade 12)",
  "Basic Education Facilities","New School Personnel Positions",
  "GAS - Senior High School Voucher Program")

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("Op. of Schools - Elementary","Op. of Schools - JHS","Op. of Schools - SHS",
                                 "Basic Education Facilities","New School Personnel Positions","SHS Voucher Program")))
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 programs have evolved (2018–2026)",
       subtitle = "School-operations lines absorb cleanly; Facilities and the SHS Voucher show widening gaps",
       x = NULL, y = NULL) +
  theme_deped() + guides(color = guide_legend(nrow = 1))

The three school-operations panels are textbook clean execution — the disbursement line shadows the allotment. Basic Education Facilities and the SHS Voucher are the visible exceptions, with disbursements falling conspicuously short of what was released. Those two are the subjects of the next two sections.

7.2 The GASTPE puzzle: demand-side subsidies

GASTPE — Government Assistance to Students and Teachers in Private Education — is public money that follows students into private schools, through two channels: the Senior High School Voucher and Educational Service Contracting (ESC) for private junior high. For most of the period both disbursed well. Then both broke.

gastpe <- pap_year %>%
  filter(pap %in% c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
         year %in% 2018:2025, !is.na(AdjAllot), AdjAllot > 0) %>%
  mutate(da = Disbursements/AdjAllot,
         pap = factor(pap, levels = c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
                      labels = c("SHS Voucher Program","ESC (Educational Service Contracting)")))

ggplot(gastpe, aes(year, da, color = pap, group = pap)) +
  geom_hline(yintercept = 1, linetype = "dotted", color = "grey60") +
  geom_line(linewidth = 1.0) + geom_point(size = 2.2) +
  geom_text(aes(label = scales::percent(da, accuracy = 1)), vjust = -1.0, size = 3.0, show.legend = FALSE, color = "grey20") +
  scale_color_manual(values = c("SHS Voucher Program" = "#D95F02","ESC (Educational Service Contracting)" = "#7570B3")) +
  scale_y_continuous(labels = percent_format(accuracy = 1), limits = c(0, 1.1), breaks = seq(0, 1, 0.25)) +
  scale_x_continuous(breaks = 2018:2025) +
  labs(title = "Disbursement-to-Allotment: GASTPE demand-side subsidies",
       subtitle = "Both programs disbursed at 80–100% through 2022, then collapsed",
       x = NULL, y = NULL) +
  theme_deped() + guides(color = guide_legend(nrow = 1))

For most of the period both lines disbursed well — the SHS Voucher ran 91–100% through 2018–2022. Then both collapsed: the Voucher fell to 76% in 2023, 53% in 2024, and 28% in 2025; ESC fell from around 80% to the mid-30s. Crucially, the allotments did not shrink — the money was appropriated and released, but not paid out. Whether the cause is a payment-processing or liquidation bottleneck, falling enrollment in the voucher program, or a deliberate slowdown, the data alone cannot say. What it can say is that the break is steep, recent, and concentrated in exactly the demand-side instruments meant to reach students outside the public system.

pap_year %>%
  filter(pap %in% c("GAS - Senior High School Voucher Program","GAS - Educational Service Contracting (ESC) for Private JHS"),
         year %in% 2018:2025) %>%
  mutate(line = ifelse(str_detect(pap,"Voucher"),"SHS Voucher","ESC"),
         da = ifelse(!is.na(AdjAllot)&AdjAllot>0, round(Disbursements/AdjAllot*100,0), NA_real_)) %>%
  select(line, year, da) %>% pivot_wider(names_from = year, values_from = da) %>%
  rename(`D/A (%)` = line) %>% kbl_clean(font = 13, na = "")
D/A (%) 2018 2019 2020 2021 2022 2023 2024 2025
ESC 87 93 66 79 82 72 34 35
SHS Voucher 91 93 96 97 100 76 53 28

7.3 Chronic low absorbers

Six procurement-heavy programs that have struggled to disburse for years are tracked below. The common thread is not the program area but the mechanism: every one of these depends on bidding, contracting, delivery, and liquidation rather than payroll.

low_paps <- c("Textbooks and Other Instructional Materials","Basic Education Facilities","Computerization Program",
              "Learning Tools and Equipment","School-Based Feeding Program (SBFP)","National Assessment Systems for Basic Education")

low_dat <- pap_year %>% filter(pap %in% low_paps) %>%
  mutate(da = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Disbursements/AdjAllot, NA_real_),
         pap = factor(pap, levels = low_paps,
                      labels = c("Textbooks & Instructional Materials","Basic Education Facilities","Computerization Program",
                                 "Learning Tools and Equipment","School-Based Feeding Program","National Assessment Systems"))) %>%
  select(pap, year, da) %>% tidyr::complete(year = 2018:2025, pap)

ggplot(low_dat, aes(year, da, 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(da, 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, 2024)) +
  labs(title = "Disbursement-to-Allotment ratios: chronic under-absorbers (2018–2025)",
       subtitle = "Textbooks has never crossed 20%; Basic Education Facilities is DepEd's infrastructure bottleneck",
       x = NULL, y = NULL) +
  theme_deped() + theme(legend.position = "none")

Textbooks and Other Instructional Materials is the standout failure: disbursement-to-allotment has stayed between 2% and 17% in every year on record — money for learning materials is appropriated and allotted, but barely paid out. Basic Education Facilities is the infrastructure bottleneck, the agency’s chronic capital-outlay problem, swinging between 16% and 54% with no clear improvement trend. The Computerization Program has been similarly weak (12–48%), with some recovery in 2024–2025, and the School-Based Feeding Program is volatile (35–87%) — a recurring annual program that nonetheless cannot disburse on a predictable schedule. The common thread is procurement, which is also where execution reform would have the most leverage.

low_dat %>% mutate(da = round(da*100,0)) %>%
  pivot_wider(names_from = year, values_from = da) %>%
  rename(`D/A (%)` = pap) %>% kbl_clean(font = 12.5, na = "")
D/A (%) 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
Textbooks & Instructional Materials 4 4 15 17 2 5 11 14
Basic Education Facilities 46 43 39 54 48 16 27 27
Computerization Program 13 27 28 23 17 12 42 48
Learning Tools and Equipment 4 7 0 1 5 20 23 10
School-Based Feeding Program 86 73 42 59 87 35 39 48
National Assessment Systems 39 14 5 10 26 21 19 23

8 Line-item reference: the FY 2027 proposal in context

The table below is the forward-looking reference for the office’s largest lines: for the top 30 P/A/Ps by the FY 2027 proposal (NEP), it gives the FY 2026 proposal and enacted budget and the most recent (2025) disbursement-to-allotment ratio, so budget levels sit beside how each line has recently absorbed. The full, unabridged P/A/P table is in the ranking section above; this one pairs budget levels with execution.

ref <- pap_year %>% filter(year == 2027, !is.na(NEP), NEP > 0) %>%
  arrange(desc(NEP)) %>% slice_head(n = 30) %>%
  transmute(pap, `NEP 2027 (B)` = NEP/1e9)

ctx <- pap_year %>% filter(year == 2026) %>%
  transmute(pap, `NEP 2026 (B)` = NEP/1e9, `GAA 2026 (B)` = GAA/1e9)
da_25 <- pap_year %>% filter(year == 2025) %>%
  transmute(pap, `D/A 2025` = ifelse(!is.na(AdjAllot) & AdjAllot > 0, Disbursements/AdjAllot, NA_real_))

ref %>% left_join(ctx, by = "pap") %>% left_join(da_25, by = "pap") %>%
  rename(`P/A/P` = pap) %>%
  dt_table(page = 15,
           money_cols = c("NEP 2027 (B)","NEP 2026 (B)","GAA 2026 (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.

9 The attached agencies

The main report covers the Office of the Secretary. DepEd also has a set of small attached agencies whose budgets are appropriated separately and are shown here on an appropriations basis only — no P/A/P-level execution data is published for them. They are a rounding error against the OSEC total (the largest, the National Museum, is proposed at ₱1.5B against OSEC’s ₱914B), but the FY 2027 proposal moves several of them sharply.

attached <- read_excel(file_path, sheet = "DepEd") %>%
  filter(UACS_AGY_DSC != "Office of the Secretary") %>%
  pivot_longer(matches("^(NEP|GAA)_\\d{4}_EXP_TOTAL$"), names_to = "var", values_to = "amount") %>%
  separate(var, into = c("metric","year","tag","ec"), sep = "_") %>%
  mutate(year = as.integer(year), amount = as.numeric(amount)) %>%
  group_by(agency = UACS_AGY_DSC, year, metric) %>%
  summarise(amount = if (all(is.na(amount))) NA_real_ else sum(amount, na.rm = TRUE), .groups = "drop")

att_2027 <- attached %>% filter(metric == "NEP", year == 2027, !is.na(amount), amount > 0) %>%
  arrange(amount) %>% mutate(agency = factor(agency, levels = agency))

ggplot(att_2027, aes(agency, amount/1e6)) +
  geom_col(fill = "#54278F", width = 0.72) +
  geom_text(aes(label = paste0(peso, scales::comma(round(amount/1e6)), "M")),
            hjust = -0.1, size = 3, color = "grey20") +
  coord_flip() +
  scale_x_discrete(labels = function(x) str_wrap(x, 34)) +
  scale_y_continuous(labels = function(v) paste0(peso, scales::comma(v), "M"),
                     expand = expansion(mult = c(0, .24))) +
  labs(title = "Attached agencies by FY 2027 NEP (proposed)",
       subtitle = "Appropriations basis only; no execution data is published for these agencies",
       x = NULL, y = NULL) +
  theme_deped() +
  theme(panel.grid.major.y = element_blank(), panel.grid.major.x = element_line(color = "grey85"))

att_tbl <- attached %>%
  filter((metric == "NEP" & year %in% c(2026, 2027)) | (metric == "GAA" & year == 2026)) %>%
  mutate(key = paste0(metric, year)) %>%
  select(agency, key, amount) %>%
  pivot_wider(names_from = key, values_from = amount) %>%
  transmute(Agency = agency,
            `NEP 2027 (M)` = NEP2027/1e6,
            `NEP 2026 (M)` = NEP2026/1e6,
            `GAA 2026 (M)` = GAA2026/1e6) %>%
  arrange(desc(`NEP 2027 (M)`))
kbl_clean(att_tbl, font = 12.5, digits = 0, format.args = list(big.mark = ","), na = "")
Agency NEP 2027 (M) NEP 2026 (M) GAA 2026 (M)
National Museum of the Philippines 1,531 812 987
Teacher Education Council 358 207 563
National Academy of Sports 254 246 541
National Book Development Board 165 152 202
Philippine High School for the Arts 131 157 218
National Council for Children’s Television 75 71 116
Early Childhood Care and Development Council

Two patterns stand out. The National Museum is proposed at ₱1.5B, nearly double its FY 2026 proposal — the single biggest mover. Several others (the Teacher Education Council, the National Academy of Sports, and the Philippine High School for the Arts) are proposed well below their FY 2026 enacted level, the familiar pattern of an Executive proposal that Congress has previously topped up. Because none of these agencies publishes P/A/P-level execution data, this appropriations-only view is as far as the absorption analysis can go for them.

10 Questions for discussion

  1. Textbooks and instructional materials. A 2–17% disbursement rate, year after year, on a line that directly affects classroom learning. What is the binding constraint — procurement, printing, delivery, or liquidation — and which of those is actually fixable within a fiscal year?
  2. The GASTPE collapse. The SHS Voucher and ESC disbursement rates have fallen sharply since 2023. Is this a payment-processing problem, an enrollment problem, or a policy decision? The answer determines whether the fix is administrative or structural.
  3. Capital Outlay restoration. The 2026 GAA raises CO to roughly ₱100B. Given CO’s 9–54% disbursement history, is the absorptive capacity there to spend it — and if not, what changes before the money is released?
  4. The aggregate-absorption blind spot. Should DepEd and its oversight bodies track and report disbursement by expense class or program type, rather than a single agency-wide figure that Personnel Services dominates and therefore flatters?
  5. The 2026 augmentation. Congress added a record ₱86B over the NEP. Where did it land, and do those lines have the capacity to absorb it — or does the augmentation simply enlarge next year’s unspent balance?

Underlying data: DBM-published budget and execution data for the DepEd 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 DepEd-OSEC budget briefing.