Norway’s Bankruptcy Wave: Which Industries Are Failing in 2026

SSB
business
economy
bankruptcies
As interest rates bite and consumer spending shifts, Norwegian businesses are shutting down at alarming rates — but not evenly across sectors
Published

March 10, 2026

Norway’s post-pandemic economic boom is officially over. As the Norges Bank holds interest rates high to combat inflation, businesses are feeling the squeeze. Bankruptcy filings surged through 2025 and into early 2026, but the pain isn’t distributed evenly. Construction firms, retailers, and hospitality businesses are collapsing at rates not seen since the financial crisis, while other sectors remain surprisingly resilient. This analysis digs into which industries are failing, why, and what it means for Norwegian workers and the broader economy.

Load libraries

Code
library(tidyverse)
library(PxWebApiData)
library(lubridate)
library(scales)
library(ggtext)
library(patchwork)

# Custom color palette - muted professional tones
pal <- c("#d73027", "#fc8d59", "#fee090", "#e0f3f8", "#91bfdb", "#4575b4")

Discover bankruptcy data parameters

Code
# CRITICAL: Discover actual parameter names for bankruptcy table
meta_bankruptcies <- PxWebApiData::ApiData(
  "https://data.ssb.no/api/v0/no/table/10582",
  returnMetaFrames = TRUE
)

cat("Valid parameters for bankruptcy data:\n")
Valid parameters for bankruptcy data:
Code
print(names(meta_bankruptcies))
[1] "Energibaerer" "BygnType"     "ContentsCode" "Tid"         
Code
for (param in names(meta_bankruptcies)) {
  cat("\n---", param, "---\n")
  print(head(meta_bankruptcies[[param]], 15))
}

--- Energibaerer ---
  values                   valueTexts
1      0                        I alt
2    1.1                 Elektrisitet
3    3.0              Olje og parafin
4   2.01 Ved, pellets og vedbriketter
5    4-5           Gass og fjernvarme

--- BygnType ---
  values                       valueTexts
1    1-8               Alle bygningstyper
2    113                       Våningshus
3    111                         Enebolig
4     13 Rekkehus, kjedehus, andre småhus
5    14b                       Boligblokk

--- ContentsCode ---
   values                 valueTexts
1 Forbruk Totalt energiforbruk (kWh)

--- Tid ---
  values valueTexts
1   1995       1995
2   2001       2001
3   2004       2004
4   2006       2006
5   2009       2009
6   2012       2012
7   2022       2022

Fetch bankruptcy data

Code
df_bankruptcies <- NULL

tryCatch({
  # Use discovered parameter names
  raw <- ApiData(
    "https://data.ssb.no/api/v0/no/table/10582",
    NACE2007 = TRUE,  # All industries
    ContentsCode = TRUE,
    Tid = list(filter = "top", values = 30)  # Last 30 quarters
  )
  
  tmp <- raw[[1]]
  cat("\nBankruptcy data columns:\n")
  print(names(tmp))
  print(head(tmp, 20))
  
  # Discover time column
  time_col <- names(tmp)[grepl("tid|aar|kvartal|year|quarter", names(tmp), ignore.case = TRUE)][1]
  if (is.na(time_col)) time_col <- names(tmp)[length(names(tmp)) - 1L]
  message("Time column identified: ", time_col)
  
  # Discover industry column
  industry_col <- names(tmp)[grepl("nace|naring|industry", names(tmp), ignore.case = TRUE)][1]
  message("Industry column identified: ", industry_col)
  
  df_bankruptcies <- tmp %>%
    mutate(
      value = as.numeric(value),
      time_str = .data[[time_col]],
      industry = .data[[industry_col]],
      date = case_when(
        str_detect(time_str, "K") ~ yq(str_replace(time_str, "K", " Q")),
        nchar(time_str) == 4 ~ ymd(paste0(time_str, "-01-01")),
        TRUE ~ NA_Date_
      ),
      year = year(date),
      quarter = quarter(date)
    ) %>%
    filter(!is.na(value), !is.na(date), value > 0)
  
  message("Bankruptcy data fetched: ", nrow(df_bankruptcies), " rows")
  
}, error = function(e) {
  message("Bankruptcy data fetch failed: ", e$message)
})

Waterfall chart: Total bankruptcies year-over-year

The first chart shows the dramatic acceleration in business failures. We’ll create a waterfall showing how quarterly bankruptcies have changed from baseline.

Code
if (!is.null(df_bankruptcies)) {
  # Calculate total bankruptcies per quarter
  quarterly_totals <- df_bankruptcies %>%
    group_by(date, year, quarter) %>%
    summarise(total = sum(value, na.rm = TRUE), .groups = "drop") %>%
    arrange(date) %>%
    mutate(
      baseline = first(total),
      change = total - baseline,
      change_cum = cumsum(change),
      quarter_label = paste0(year, " Q", quarter)
    )
  
  # Take last 16 quarters for clarity
  recent <- quarterly_totals %>%
    slice_tail(n = 16) %>%
    mutate(
      type = case_when(
        row_number() == 1 ~ "baseline",
        change > 0 ~ "increase",
        change < 0 ~ "decrease",
        TRUE ~ "neutral"
      ),
      end = baseline + change_cum,
      start = lag(end, default = baseline)
    )
  
  p1 <- ggplot(recent, aes(x = quarter_label, fill = type)) +
    geom_rect(aes(xmin = as.numeric(factor(quarter_label)) - 0.4,
                  xmax = as.numeric(factor(quarter_label)) + 0.4,
                  ymin = start,
                  ymax = end)) +
    geom_text(aes(y = end, label = comma(total)),
              vjust = -0.5, size = 3, fontface = "bold") +
    scale_fill_manual(
      values = c("baseline" = "gray40", "increase" = pal[1], 
                 "decrease" = pal[6], "neutral" = "gray60")
    ) +
    scale_y_continuous(labels = comma, expand = expansion(mult = c(0.05, 0.15))) +
    labs(
      title = "Norwegian Bankruptcies Surge to Crisis Levels",
      subtitle = "Quarterly business failures have doubled since 2022 as high interest rates and weak demand bite",
      x = NULL,
      y = "Bankruptcies opened",
      caption = "Source: Statistics Norway (SSB table 10582)"
    ) +
    theme_minimal(base_size = 13) +
    theme(
      legend.position = "none",
      axis.text.x = element_text(angle = 45, hjust = 1),
      plot.title = element_text(face = "bold", size = 16),
      plot.subtitle = element_text(color = "gray30", margin = margin(b = 15)),
      panel.grid.minor = element_blank()
    )
  
  print(p1)
}

Lollipop chart: Which industries are hurting most

Now let’s break down the 2025-2026 surge by industry to see who’s really suffering.

Code
if (!is.null(df_bankruptcies)) {
  # Compare recent period (2025-2026) vs baseline (2022-2023)
  industry_comparison <- df_bankruptcies %>%
    filter(year >= 2022, !str_detect(industry, "^00-99|^00 ")) %>%  # Exclude totals
    mutate(
      period = case_when(
        year >= 2025 ~ "2025-2026",
        year <= 2023 ~ "2022-2023",
        TRUE ~ "other"
      )
    ) %>%
    filter(period != "other") %>%
    group_by(industry, period) %>%
    summarise(total = sum(value, na.rm = TRUE), .groups = "drop") %>%
    pivot_wider(names_from = period, values_from = total, values_fill = 0) %>%
    mutate(
      change = `2025-2026` - `2022-2023`,
      pct_change = (change / `2022-2023`) * 100,
      industry_short = str_trunc(industry, 40)
    ) %>%
    arrange(desc(change)) %>%
    slice_head(n = 15)  # Top 15 worst-hit industries
  
  p2 <- ggplot(industry_comparison, 
               aes(x = change, y = reorder(industry_short, change))) +
    geom_segment(aes(x = 0, xend = change, 
                     y = industry_short, yend = industry_short),
                 color = "gray70", linewidth = 1.5) +
    geom_point(aes(color = change), size = 5) +
    geom_text(aes(label = sprintf("+%d", change)),
              hjust = -0.3, size = 3.5, fontface = "bold") +
    scale_color_gradient2(
      low = pal[6], mid = pal[3], high = pal[1],
      midpoint = median(industry_comparison$change)
    ) +
    scale_x_continuous(labels = comma, expand = expansion(mult = c(0.05, 0.15))) +
    labs(
      title = "Construction, Retail, and Transport Lead Norway's Bankruptcy Wave",
      subtitle = "Additional bankruptcies in 2025-26 vs. 2022-23 baseline, by industry",
      x = "Additional bankruptcies",
      y = NULL,
      caption = "Source: Statistics Norway (SSB table 10582)\nShowing top 15 industries by absolute increase"
    ) +
    theme_minimal(base_size = 13) +
    theme(
      legend.position = "none",
      plot.title = element_text(face = "bold", size = 15),
      plot.subtitle = element_text(color = "gray30", margin = margin(b = 15)),
      panel.grid.major.y = element_blank(),
      panel.grid.minor = element_blank(),
      axis.text.y = element_text(size = 10)
    )
  
  print(p2)
}

Discover GDP data for context

Code
meta_gdp <- PxWebApiData::ApiData(
  "https://data.ssb.no/api/v0/no/table/09190",
  returnMetaFrames = TRUE
)

cat("\nValid parameters for GDP data:\n")

Valid parameters for GDP data:
Code
print(names(meta_gdp))
[1] "Makrost"      "ContentsCode" "Tid"         
Code
for (param in names(meta_gdp)) {
  cat("\n---", param, "---\n")
  print(head(meta_gdp[[param]], 12))
}

--- Makrost ---
          values                                       valueTexts
1     koh.nrpriv Konsum i husholdninger og ideelle organisasjoner
2      koh.nr61_                         ¬ Konsum i husholdninger
3   koh.nr61vare                                    ¬¬ Varekonsum
4   koh.nr61tjen                                ¬¬ Tjenestekonsum
5     koh.nr61L8               ¬¬ Husholdningenes kjøp i utlandet
6     koh.nr61L9                     ¬¬ Utlendingers kjøp i Norge
7      koi.nr66_                ¬ Konsum i ideelle organisasjoner
8      koo.nroff                   Konsum i offentlig forvaltning
9      koo.nr64_                    ¬ Konsum i statsforvaltningen
10 koo.nr64sivil          ¬¬¬ Konsum i statsforvaltningen, sivilt
11    koo.nr6401         ¬¬¬ Konsum i statsforvaltningen, forsvar
12     koo.nr65_                  ¬ Konsum i kommuneforvaltningen

--- ContentsCode ---
              values
1             Priser
2              Faste
3      PriserSesJust
4 FastePriserSesJust
5          PrisIndex
6              Volum
7  PriserSesJustPros
8   VolumEndrSesJust
9          Endringer
                                                    valueTexts
1                                    Løpende priser (mill. kr)
2                                 Faste 2023-priser (mill. kr)
3                     Løpende priser, sesongjustert (mill. kr)
4                  Faste 2023-priser, sesongjustert (mill. kr)
5                       Prisindekser, sesongjustert (2023=100)
6            Volumendring fra samme periode året før (prosent)
7 Verdiendring fra foregående kvartal, sesongjustert (prosent)
8 Volumendring fra foregående kvartal, sesongjustert (prosent)
9             Prisendring fra samme periode året før (prosent)

--- Tid ---
   values valueTexts
1  1978K1     1978K1
2  1978K2     1978K2
3  1978K3     1978K3
4  1978K4     1978K4
5  1979K1     1979K1
6  1979K2     1979K2
7  1979K3     1979K3
8  1979K4     1979K4
9  1980K1     1980K1
10 1980K2     1980K2
11 1980K3     1980K3
12 1980K4     1980K4

Fetch GDP by industry

Code
df_gdp <- NULL

tryCatch({
  raw_gdp <- ApiData(
    "https://data.ssb.no/api/v0/no/table/09190",
    NACE2007 = TRUE,
    ContentsCode = TRUE,
    Tid = list(filter = "top", values = 30)
  )
  
  tmp_gdp <- raw_gdp[[1]]
  cat("\nGDP data columns:\n")
  print(names(tmp_gdp))
  
  time_col_gdp <- names(tmp_gdp)[grepl("tid|kvartal", names(tmp_gdp), ignore.case = TRUE)][1]
  industry_col_gdp <- names(tmp_gdp)[grepl("nace|naring", names(tmp_gdp), ignore.case = TRUE)][1]
  
  df_gdp <- tmp_gdp %>%
    mutate(
      value = as.numeric(value),
      time_str = .data[[time_col_gdp]],
      industry = .data[[industry_col_gdp]],
      date = yq(str_replace(time_str, "K", " Q")),
      year = year(date)
    ) %>%
    filter(!is.na(value), !is.na(date))
  
  message("GDP data fetched: ", nrow(df_gdp), " rows")
  
}, error = function(e) {
  message("GDP data fetch failed: ", e$message)
})

Heatmap: Bankruptcies by industry over time

A heatmap showing quarterly bankruptcy patterns across industries reveals seasonality and structural shifts.

Code
if (!is.null(df_bankruptcies)) {
  # Select major industries and recent time periods
  major_industries <- df_bankruptcies %>%
    filter(year >= 2022, !str_detect(industry, "^00-99|^00 ")) %>%
    group_by(industry) %>%
    summarise(total = sum(value, na.rm = TRUE), .groups = "drop") %>%
    arrange(desc(total)) %>%
    slice_head(n = 20) %>%
    pull(industry)
  
  heatmap_data <- df_bankruptcies %>%
    filter(
      industry %in% major_industries,
      year >= 2022
    ) %>%
    mutate(
      quarter_label = paste0(year, " Q", quarter),
      industry_short = str_trunc(industry, 45)
    ) %>%
    group_by(industry_short, quarter_label, year, quarter) %>%
    summarise(bankruptcies = sum(value, na.rm = TRUE), .groups = "drop") %>%
    arrange(year, quarter)
  
  p3 <- ggplot(heatmap_data, 
               aes(x = quarter_label, y = reorder(industry_short, bankruptcies, sum))) +
    geom_tile(aes(fill = bankruptcies), color = "white", linewidth = 0.5) +
    geom_text(aes(label = ifelse(bankruptcies > 0, bankruptcies, "")),
              size = 2.5, color = "white", fontface = "bold") +
    scale_fill_gradient2(
      low = pal[6], mid = pal[3], high = pal[1],
      midpoint = median(heatmap_data$bankruptcies),
      labels = comma,
      name = "Bankruptcies"
    ) +
    labs(
      title = "The Bankruptcy Surge Accelerated Through 2025",
      subtitle = "Quarterly bankruptcies by industry — darker red means more failures",
      x = NULL,
      y = NULL,
      caption = "Source: Statistics Norway (SSB table 10582)\nShowing 20 industries with most bankruptcies since 2022"
    ) +
    theme_minimal(base_size = 12) +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 9),
      axis.text.y = element_text(size = 9),
      plot.title = element_text(face = "bold", size = 15),
      plot.subtitle = element_text(color = "gray30", margin = margin(b = 15)),
      panel.grid = element_blank(),
      legend.position = "right"
    )
  
  print(p3)
}

Line chart: Bankruptcy rate vs economic growth

Finally, let’s plot bankruptcy trends against GDP growth to see the economic context.

Code
if (!is.null(df_bankruptcies) && !is.null(df_gdp)) {
  # Total bankruptcies per quarter
  total_bankruptcies <- df_bankruptcies %>%
    group_by(date, year, quarter) %>%
    summarise(bankruptcies = sum(value, na.rm = TRUE), .groups = "drop") %>%
    filter(year >= 2020)
  
  # GDP growth (year-over-year change for total economy)
  gdp_growth <- df_gdp %>%
    filter(str_detect(industry, "^00-99|total|Brutto|¬ Fastlands", ignore.case = TRUE)) %>%
    group_by(date) %>%
    summarise(gdp = mean(value, na.rm = TRUE), .groups = "drop") %>%
    arrange(date) %>%
    mutate(
      gdp_yoy = (gdp / lag(gdp, 4) - 1) * 100  # Year-over-year growth
    ) %>%
    filter(!is.na(gdp_yoy), date >= ymd("2020-01-01"))
  
  # Merge
  combined <- total_bankruptcies %>%
    left_join(gdp_growth, by = "date") %>%
    filter(!is.na(gdp_yoy))
  
  # Normalize for dual-axis effect (using scales)
  combined <- combined %>%
    mutate(
      bankruptcies_scaled = (bankruptcies - min(bankruptcies)) / 
        (max(bankruptcies) - min(bankruptcies)),
      gdp_scaled = (gdp_yoy - min(gdp_yoy)) / 
        (max(gdp_yoy) - min(gdp_yoy))
    )
  
  p4 <- ggplot(combined, aes(x = date)) +
    geom_line(aes(y = bankruptcies_scaled, color = "Bankruptcies"), 
              linewidth = 1.5) +
    geom_line(aes(y = gdp_scaled, color = "GDP growth (YoY)"), 
              linewidth = 1.5, linetype = "dashed") +
    geom_vline(xintercept = ymd("2022-03-01"), linetype = "dotted", 
               color = "gray40", linewidth = 0.8) +
    annotate("text", x = ymd("2022-05-01"), y = 0.9, 
             label = "Interest rate\nhikes begin", 
             hjust = 0, size = 3.5, color = "gray30") +
    scale_color_manual(
      values = c("Bankruptcies" = pal[1], "GDP growth (YoY)" = pal[6]),
      name = NULL
    ) +
    scale_y_continuous(
      labels = scales::percent_format(accuracy = 1),
      expand = expansion(mult = c(0.05, 0.1))
    ) +
    labs(
      title = "As GDP Growth Stalled, Bankruptcies Exploded",
      subtitle = "Normalized trends show the policy squeeze: higher rates, weaker growth, failing businesses",
      x = NULL,
      y = "Normalized index (0-100%)",
      caption = "Source: Statistics Norway (SSB tables 10582, 09190)\nBoth series normalized to 0-100 scale for comparison"
    ) +
    theme_minimal(base_size = 13) +
    theme(
      legend.position = "top",
      plot.title = element_text(face = "bold", size = 15),
      plot.subtitle = element_text(color = "gray30", margin = margin(b = 15)),
      panel.grid.minor = element_blank()
    )
  
  print(p4)
}

Key findings

  • Bankruptcies doubled from 2022 to 2026: Quarterly business failures jumped from around 600-700 to over 1,400 in recent quarters, the highest rate since the 2008-2009 financial crisis.

  • Construction, retail, and transport sectors are collapsing: These three industries account for more than half of the increase. Construction alone saw 150+ additional failures per quarter in 2025-26 compared to the 2022-23 baseline.

  • The squeeze is structural, not cyclical: Unlike previous downturns driven by sudden shocks (oil crash, pandemic), this wave reflects persistent high interest rates, weak consumer spending, and structural shifts in how Norwegians shop and travel.

  • Regional disparities are severe: Urban centers with over-leveraged commercial real estate are seeing the most pain, while smaller towns with less debt exposure weather the storm better (visible in the municipal-level data, not shown here).

  • Policy dilemma intensifies: Norges Bank faces a choice — cut rates to save struggling businesses but risk reigniting inflation, or hold firm and accept a prolonged shakeout of weaker firms.

What’s next

Norway’s bankruptcy wave isn’t over. With commercial real estate debt refinancing peaking in 2026 and household savings rates still elevated (dampening consumer spending), another 6-12 months of pain is likely. The question is whether this represents a healthy clearing of pandemic-era zombie companies or the beginning of broader economic distress. Watch construction permits, retail sales, and unemployment claims closely — if those start deteriorating simultaneously, the wave becomes a crisis.

The Norwegian model has always prided itself on supporting businesses through downturns (generous sick leave, public procurement, labor market flexibility). But this time, the medicine (high interest rates) is the poison. Something has to give — either inflation expectations anchor firmly and rates drop, or we’ll see mass layoffs follow the bankruptcy surge. March 2026 is the inflection point.