Skip to content

Euro area government deficit at 3.1% and EU at 3.2% of GDP

[]
{ if (configuration.isSticky) { fragmentElement.style.height = ‘100%’; // Set the height of the fragment element if sticky configuration is enabled } const parentRow = fragmentElement.closest(‘.row, .ecl-row’); // Find the closest parent row element const selector = buildSelector(configuration); // Build the CSS selector based on configuration const headings = Array.from(parentRow.querySelectorAll(selector)); // Get all headings within the parent row const tableOfContents = buildTableOfContents(headings); // Build the table of contents from the headings const navList = fragmentElement.querySelector(‘.estat-inpage-nav__list’); // Get the navigation list element generateList(navList, tableOfContents); // Generate the navigation list from the table of contents const topMargin = document.querySelector(‘.has-control-menu’) ? 120 : 66; // Determine the top margin based on the presence of a control menu const observeHeadings = new IntersectionObserver( (entries) => observeScrolling(entries, topMargin, headings), { rootMargin: `-${topMargin}px 0px 0px 0px` } // Set the root margin for the intersection observer ); headings.forEach(heading => observeHeadings.observe(heading)); // Observe each heading for intersection changes setupEventListeners(fragmentElement, headings); // Set up event listeners for the navigation elements document.getElementById(‘skip-inpage-navigation’).href = `#${headings[0]?.id}`; // Set the href for the skip navigation link const spinner = fragmentElement.querySelector(‘.ecl-spinner.ecl-spinner–visible’); // Get the spinner element spinner.classList.remove(‘ecl-spinner–visible’); // Hide the spinner fragmentElement.querySelector(‘.estat-inpage-nav’).classList.remove(‘ecl-u-d-none’); // Show the navigation element }); /** * Builds a CSS selector string based on the configuration object. * @param {Object} configuration – Configuration object containing heading levels and other settings. * @returns {string} – The CSS selector string. */ function buildSelector(configuration) { let selector = ”; const deepestLevel = configuration.headingLevel.slice(-1); // Get the deepest heading level from the configuration const topLevel = 2; // Define the top level heading for (let i = topLevel; i topLevel) { selector += ‘, ‘; // Add a comma separator for multiple selectors } selector += `h${i}`; // Add the heading level to the selector if (!configuration.includeNonECLHeadings) { selector += `.ecl-u-type-heading-${i}`; // Add the ECL heading class if non-ECL headings are not included } if (configuration.selectorToExclude) { selector += `:not(${configuration.selectorToExclude})`; // Exclude specific selectors if defined in the configuration } } return selector; } /** * Builds a table of contents array from the provided headings. * @param {Array} headings – Array of heading elements. * @returns {Array} – The table of contents array. */ function buildTableOfContents(headings) { let tableOfContents = []; headings.forEach((heading, i) => { if (!heading.id) { heading.id = ‘estat-inpage-nav-heading-‘ + i; // Assign a unique ID to the heading if it doesn’t have one } const objEl = { ‘id’: heading.id, ‘content’: heading.innerText, level: heading.nodeName.slice(-1) – 1, // Determine the heading level children: [] }; addHeadingToTableOfContents(objEl, tableOfContents); // Add the heading to the table of contents }); return tableOfContents; } /** * Adds a heading object to the table of contents array. * @param {Object} objEl – Heading object to add. * @param {Array} tableOfContents – The table of contents array. */ function addHeadingToTableOfContents(objEl, tableOfContents) { if (objEl.level === 1) { tableOfContents.push(objEl); // Add level 1 headings directly to the table of contents } else if (objEl.level === 2) { tableOfContents[tableOfContents.length – 1].children.push(objEl); // Add level 2 headings as children of the last level 1 heading } else if (objEl.level === 3) { const childrenArr = tableOfContents[tableOfContents.length – 1].children; childrenArr[childrenArr.length – 1].children.push(objEl); // Add level 3 headings as children of the last level 2 heading } } /** * Generates a nested list of navigation links from the table of contents array. * @param {HTMLElement} ulElement – The unordered list element to populate. * @param {Array} headingArray – Array of heading objects. */ function generateList(ulElement, headingArray) { headingArray.forEach((heading, i) => { const li = document.createElement(‘li’); li.className = ‘estat-inpage-nav__list-item’; ulElement.appendChild(li); const link = `${heading.content}` if (heading.children.length > 0) { const containerDiv = document.createElement(‘div’) const button = `

Printing can have negative environmental impacts due to paper waste. We encourage you to explore eco-friendly alternatives. Bookmarking this page in your browser allows you to access it anytime.

This publication can also be converted to PDF, if you have a PDF printer installed on your computer. PDF printers function as virtual printers, enabling you to create digital copies of web pages and access the content offline.

{ const buttonPrintPage = document.getElementById(‘estat-print-page-modal-toggle’); const cookieSkipModal = ‘skipModalBeforePrinting’; if (configuration.displayInPageHeader) { const headerElement = document.querySelector(‘.ecl-page-header .ecl-page-header__meta’) || document.querySelector(‘.ecl-page-header .ecl-page-header__title-container ‘) if (headerElement) { headerElement.prepend(buttonPrintPage); headerElement.classList.add(‘ecl-u-width-100’) } } buttonPrintPage.addEventListener(‘click’, () => { const skipModal = readCookie(cookieSkipModal); if (skipModal == ‘true’) { window.print(); } else { const eclModalElement = document.getElementById(‘estat-print-page-modal’); const eclModal = ECL.components.get(eclModalElement); eclModal.openModal(); } }); document.getElementById(‘print-submit’).addEventListener(‘click’, () => { const skipModal = document.getElementById(‘checkbox-skip-modal’).checked if (skipModal) { writeCookieWithMaxAgeValue(cookieSkipModal, ‘true’, 15768000); } else { deleteCookie(cookieSkipModal); } window.print(); }); });;}());]]>

Government debt at 87.4% and 81.0% respectively

Overview

In the euro area the government deficit to GDP ratio decreased from 3.5% in 2023 to 3.1% in 2024, and in the EU from 3.5% to 3.2%. In the euro area the government debt to GDP ratio slightly increased from 87.3% at the end of 2023 to 87.4% at the end of 2024, and in the EU from 80.8% to 81.0%.

In this release, Eurostat, the statistical office of the European Union, is providing government deficit and debt data for the years 2021-2024, based on figures reported by EU Member States in the first notification in 2025, for the application of the excessive deficit procedure (EDP). This notification is based on the ESA 2010 system of national accounts. This release also includes data on government expenditure and revenue.

Deficit and debt data for Euro area and EU

 

 

2021

2022

2023

2024

 

 

 

 

 

(million euro)

12 613 587

13 722 911

14 604 759

15 160 962

(million euro)

-643 043

-475 295

-515 536

-468 580

% of GDP

-5.1

-3.5

-3.5

-3.1

% of GDP

52.0

50.0

49.5

49.6

% of GDP

46.9

46.5

46.0

46.5

(million euro)

11 840 208

12 288 469

12 753 756

13 258 118

% of GDP

93.9

89.5

87.3

87.4

 

 

 

 

 

(million euro)

14 795 045

16 142 589

17 208 671

17 950 185

(million euro)

-683 497

-519 214

-595 476

-568 073

% of GDP

-4.6

-3.2

-3.5

-3.2

% of GDP

51.1

49.2

49.0

49.2

% of GDP

46.5

46.0

45.5

46.0

(million euro)

12 835 106

13 320 383

13 901 072

14 543 529

% of GDP

86.8

82.5

80.8

81.0

In 2024, all Member States, except Denmark (+4.5%), Ireland and Cyprus (both +4.3%), Greece (+1.3%), Luxembourg (+1.0) and Portugal (+0.7%), reported a deficit. The highest deficits were recorded in Romania (‑9.3%), Poland (-6.6%), France (‑5.8%) and Slovakia (-5.3%). Twelve Member States had deficits equal to or higher than 3% of GDP.

At the end of 2024, the lowest ratios of government debt to GDP were recorded in Estonia (23.6%), Bulgaria (24.1%), Luxembourg (26.3%), Denmark (31.1%), Sweden (33.5%) and Lithuania (38.2%). Twelve Member States had government debt ratios higher than 60% of GDP, with the highest registered in Greece (153.6%), Italy (135.3%), France (113.0%), Belgium (104.7%) and Spain (101.8%).

In 2024, government expenditure in the euro area was equivalent to 49.6% of GDP and government revenue to 46.5%. The figures for the EU were 49.2% and 46.0%, respectively. Government revenue and expenditure ratios increased both in the euro area and the EU, compared to 2023.

Reservations on reported data

Eurostat is withdrawing its reservation on the quality of data reported by Estonia for 2023 with respect to the appropriate time of recording of military expenditure. The Estonian statistical authorities recorded the relevant expenditures in 2023.

Amendment by Eurostat to reported data

Eurostat has made no amendments to the data reported by Member States.

Tables

GDP, government deficit/surplus and debt in the EU
(in national currencies)

2021

2022

2023

2024

 

 

 

 

(million euro)

506 047

563 711

596 203

613 984

(million euro)

-27 335

-20 406

-24 420

-27 750

(% of GDP)

-5.4

-3.6

-4.1

-4.5

(% of GDP)

54.9

52.3

53.3

54.5

(% of GDP)

49.5

48.6

49.2

50.0

(million euro)

549 266

578 936

615 573

642 875

(% of GDP)

108.5

102.7

103.2

104.7

(million euro)

8 744

8 567

8 357

8 059

(% of GDP)

1.7

1.5

1.4

1.3

 

 

 

 

(million BGN)

139 602

168 360

185 233

202 861

(million BGN)

-5 535

-4 968

-3 678

-6 158

(% of GDP)

-4.0

-3.0

-2.0

-3.0

(% of GDP)

41.5

41.3

38.8

39.8

(% of GDP)

37.5

38.3

36.8

36.7

(million BGN)

33 279

37 855

42 393

48 846

(% of GDP)

23.8

22.5

22.9

24.1

(million BGN)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million CZK)

6 307 755

7 049 872

7 618 528

8 010 659

(million CZK)

-312 308

-216 345

-286 066

-177 173

(% of GDP)

-5.0

-3.1

-3.8

-2.2

(% of GDP)

45.0

43.0

43.9

43.0

(% of GDP)

40.1

39.9

40.2

40.8

(million CZK)

2 566 752

2 997 632

3 234 077

3 491 908

(% of GDP)

40.7

42.5

42.5

43.6

(million CZK)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

(million DKK)

2 567 520

2 844 228

2 804 742

2 960 886

(million DKK)

105 216

97 945

92 724

133 229

(% of GDP)

4.1

3.4

3.3

4.5

(% of GDP)

49.4

44.9

46.8

46.5

(% of GDP)

53.5

48.3

50.1

51.0

(million DKK)

1 039 517

969 223

942 073

920 586

(% of GDP)

40.5

34.1

33.6

31.1

(million DKK)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

3 676 460

3 953 850

4 185 550

4 305 260

(million euro)

-116 436

-84 875

-103 799

-118 777

(% of GDP)

-3.2

-2.1

-2.5

-2.8

(% of GDP)

50.7

49.0

48.4

49.5

(% of GDP)

47.5

46.9

45.9

46.8

(million euro)

2 503 656

2 570 847

2 632 103

2 688 879

(% of GDP)

68.1

65.0

62.9

62.5

(million euro)

68 128

66 900

65 755

62 928

(% of GDP)

1.9

1.7

1.6

1.5

 

 

 

 

(million euro)

31 456

36 443

38 188

39 510

(million euro)

-808

-392

-1 199

-601

(% of GDP)

-2.6

-1.1

-3.1

-1.5

(% of GDP)

42.1

40.0

43.7

44.0

(% of GDP)

39.5

38.9

40.5

42.5

(million euro)

5 794

6 965

7 708

9 327

(% of GDP)

18.4

19.1

20.2

23.6

(million euro)

480

482

481

481

(% of GDP)

1.5

1.3

1.3

1.2

 

 

 

 

(million euro)

449 217

520 935

509 952

533 444

(million euro)

-6 126

8 692

7 900

23 180

(% of GDP)

-1.4

1.7

1.5

4.3

(% of GDP)

23.5

20.6

22.7

23.5

(% of GDP)

22.2

22.3

24.3

27.8

(million euro)

236 119

224 771

220 721

218 178

(% of GDP)

52.6

43.1

43.3

40.9

(million euro)

318

284

249

197

(% of GDP)

0.1

0.1

0.0

0.0

 

 

 

 

(million euro)

184 575

207 854

225 197

237 573

(million euro)

-13 044

-5 104

-3 042

3 181

(% of GDP)

-7.1

-2.5

-1.4

1.3

(% of GDP)

56.7

52.8

49.5

48.0

(% of GDP)

49.7

50.4

48.2

49.3

(million euro)

364 141

368 005

369 110

364 885

(% of GDP)

197.3

177.0

163.9

153.6

(million euro)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

1 235 474

1 373 629

1 498 324

1 591 627

(million euro)

-82 174

-63 105

-52 669

-50 187

(% of GDP)

-6.7

-4.6

-3.5

-3.2

(% of GDP)

49.5

46.4

45.4

45.4

(% of GDP)

42.8

41.8

41.9

42.3

(million euro)

1 429 404

1 504 105

1 575 378

1 620 602

(% of GDP)

115.7

109.5

105.1

101.8

(million euro)

29 867

29 329

28 608

27 589

(% of GDP)

2.4

2.1

1.9

1.7

 

 

 

 

(million euro)

2 508 102

2 653 997

2 826 542

2 925 642

(million euro)

-165 149

-125 896

-151 709

-169 572

(% of GDP)

-6.6

-4.7

-5.4

-5.8

(% of GDP)

59.5

58.4

56.9

57.1

(% of GDP)

52.9

53.7

51.5

51.3

(million euro)

2 828 781

2 955 639

3 102 542

3 305 287

(% of GDP)

112.8

111.4

109.8

113.0

(million euro)

51 150

50 228

48 993

47 248

(% of GDP)

2.0

1.9

1.7

1.6

 

 

 

 

(million euro)

58 347

67 615

78 060

85 610

(million euro)

-1 505

82

-618

-2 026

(% of GDP)

-2.6

0.1

-0.8

-2.4

(% of GDP)

48.1

45.0

46.8

48.0

(% of GDP)

45.5

45.1

46.0

45.6

(million euro)

45 629

46 347

48 262

49 283

(% of GDP)

78.2

68.5

61.8

57.6

(million euro)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

1 842 507

1 998 073

2 131 390

2 192 182

(million euro)

-163 603

-162 030

-154 284

-75 547

(% of GDP)

-8.9

-8.1

-7.2

-3.4

(% of GDP)

56.0

54.9

54.0

50.6

(% of GDP)

47.2

46.8

46.7

47.1

(million euro)

2 686 605

2 764 237

2 869 648

2 966 597

(% of GDP)

145.8

138.3

134.6

135.3

(million euro)

44 932

44 122

43 037

41 503

(% of GDP)

2.4

2.2

2.0

1.9

 

 

 

 

(million euro)

25 680

29 377

31 340

33 568

(million euro)

-417

783

532

1 437

(% of GDP)

-1.6

2.7

1.7

4.3

(% of GDP)

42.7

38.1

42.0

40.0

(% of GDP)

41.1

40.8

43.7

44.3

(million euro)

24 776

23 813

23 081

21 828

(% of GDP)

96.5

81.1

73.6

65.0

(million euro)

364

355

343

327

(% of GDP)

1.4

1.2

1.1

1.0

 

 

 

 

(million euro)

32 284

36 100

39 372

40 208

(million euro)

-2 331

-1 754

-932

-706

(% of GDP)

-7.2

-4.9

-2.4

-1.8

(% of GDP)

46.5

44.2

43.7

45.7

(% of GDP)

39.3

39.4

41.3

43.9

(million euro)

14 810

16 039

17 579

18 800

(% of GDP)

45.9

44.4

44.6

46.8

(million euro)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

56 680

67 455

73 793

78 410

(million euro)

-654

-482

-508

-1 006

(% of GDP)

-1.2

-0.7

-0.7

-1.3

(% of GDP)

37.3

36.3

37.4

39.5

(% of GDP)

36.2

35.5

36.7

38.2

(million euro)

24 535

25 672

27 558

29 972

(% of GDP)

43.3

38.1

37.3

38.2

(million euro)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

73 039

76 731

80 992

86 104

(million euro)

732

141

-640

888

(% of GDP)

1.0

0.2

-0.8

1.0

(% of GDP)

42.4

44.3

47.0

46.9

(% of GDP)

43.4

44.5

46.2

47.9

(million euro)

17 664

19 107

20 268

22 654

(% of GDP)

24.2

24.9

25.0

26.3

(million euro)

667

656

640

619

(% of GDP)

0.9

0.9

0.8

0.7

 

 

 

 

(million HUF)

55 560 466

66 149 434

75 568 873

81 514 214

(million HUF)

-3 950 388

-4 082 489

-5 099 514

-4 006 439

(% of GDP)

-7.1

-6.2

-6.7

-4.9

(% of GDP)

48.1

48.7

49.2

46.9

(% of GDP)

41.0

42.5

42.4

42.0

(million HUF)

42 345 225

48 856 449

55 139 767

59 875 234

(% of GDP)

76.2

73.9

73.0

73.5

(million HUF)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

16 676

18 270

20 541

22 471

(million euro)

-1 161

-954

-972

-825

(% of GDP)

-7.0

-5.2

-4.7

-3.7

(% of GDP)

39.5

37.7

36.7

38.3

(% of GDP)

32.5

32.5

32.0

34.6

(million euro)

8 305

9 052

9 831

10 648

(% of GDP)

49.8

49.5

47.9

47.4

(million euro)

227

223

218

210

(% of GDP)

1.4

1.2

1.1

0.9

 

 

 

 

(million euro)

891 550

993 820

1 067 599

1 134 115

(million euro)

-19 599

115

-3 820

-10 084

(% of GDP)

-2.2

0.0

-0.4

-0.9

(% of GDP)

45.9

43.2

43.2

43.9

(% of GDP)

43.7

43.3

42.8

43.0

(million euro)

450 239

481 145

482 228

491 585

(% of GDP)

50.5

48.4

45.2

43.3

(million euro)

14 345

14 086

13 740

13 850

(% of GDP)

1.6

1.4

1.3

1.2

 

 

 

 

(million euro)

406 232

448 007

473 227

481 940

(million euro)

-23 129

-15 325

-12 377

-22 484

(% of GDP)

-5.7

-3.4

-2.6

-4.7

(% of GDP)

56.0

53.1

52.7

56.3

(% of GDP)

50.3

49.7

50.1

51.6

(million euro)

334 713

351 131

371 520

394 131

(% of GDP)

82.4

78.4

78.5

81.8

(million euro)

6 984

6 858

6 689

6 451

(% of GDP)

1.7

1.5

1.4

1.3

 

 

 

 

(million PLN)

2 661 518

3 100 850

3 415 274

3 641 208

(million PLN)

-46 450

-106 587

-180 078

-239 809

(% of GDP)

-1.7

-3.4

-5.3

-6.6

(% of GDP)

43.6

43.2

46.9

49.4

(% of GDP)

41.8

39.8

41.6

42.8

(million PLN)

1 410 966

1 512 812

1 691 243

2 011 840

(% of GDP)

53.0

48.8

49.5

55.3

(million PLN)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

216 494

243 957

267 923

285 189

(million euro)

-6 117

-757

3 247

1 994

(% of GDP)

-2.8

-0.3

1.2

0.7

(% of GDP)

47.3

43.9

42.3

42.8

(% of GDP)

44.5

43.6

43.5

43.5

(million euro)

268 189

271 358

261 849

270 723

(% of GDP)

123.9

111.2

97.7

94.9

(million euro)

1 054

953

852

701

(% of GDP)

0.5

0.4

0.3

0.2

 

 

 

 

(million RON)

1 192 285

1 389 450

1 604 554

1 760 118

(million RON)

-85 177

-89 370

-105 639

-163 749

(% of GDP)

-7.1

-6.4

-6.6

-9.3

(% of GDP)

39.8

40.7

40.6

43.5

(% of GDP)

32.6

34.3

34.0

34.1

(million RON)

576 339

665 491

784 235

963 941

(% of GDP)

48.3

47.9

48.9

54.8

(million RON)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

 

 

 

 

(million euro)

52 023

56 909

63 951

66 968

(million euro)

-2 399

-1 715

-1 656

-630

(% of GDP)

-4.6

-3.0

-2.6

-0.9

(% of GDP)

49.9

47.7

46.5

46.8

(% of GDP)

45.3

44.6

43.9

45.8

(million euro)

38 930

41 395

43 739

44 895

(% of GDP)

74.8

72.7

68.4

67.0

(million euro)

1 182

1 161

1 133

1 092

(% of GDP)

2.3

2.0

1.8

1.6

 

 

 

 

(million euro)

101 934

110 046

123 833

130 985

(million euro)

-5 189

-1 836

-6 427

-6 907

(% of GDP)

-5.1

-1.7

-5.2

-5.3

(% of GDP)

44.9

43.0

48.0

47.1

(% of GDP)

39.8

41.3

42.8

41.8

(million euro)

61 346

63 499

68 896

77 648

(% of GDP)

60.2

57.7

55.6

59.3

(million euro)

1 967

1 978

1 973

1 971

(% of GDP)

1.9

1.8

1.6

1.5

 

 

 

 

(million euro)

248 764

266 135

272 782

276 172

(million euro)

-6 598

-477

-8 144

-12 159

(% of GDP)

-2.7

-0.2

-3.0

-4.4

(% of GDP)

55.1

52.6

55.9

57.6

(% of GDP)

52.5

52.5

53.0

53.2

(million euro)

182 096

197 015

211 539

226 701

(% of GDP)

73.2

74.0

77.5

82.1

(million euro)

4 510

4 429

4 320

4 166

(% of GDP)

1.8

1.7

1.6

1.5

 

 

 

 

(million SEK)

5 464 876

5 865 211

6 212 143

6 447 503

(million SEK)

-11 062

59 140

-48 547

-96 104

(% of GDP)

-0.2

1.0

-0.8

-1.5

(% of GDP)

50.0

48.9

49.4

50.0

(% of GDP)

49.8

49.9

48.6

48.5

(million SEK)

2 016 846

1 984 255

1 964 555

2 158 987

(% of GDP)

36.9

33.8

31.6

33.5

(million SEK)

0

0

0

0

(% of GDP)

0.0

0.0

0.0

0.0

Notes for users

Revisions and timetable

In the previous provision of data for the excessive deficit procedure, the 2023 government deficit for the euro area was 3.6% of GDP, for the EU it was 3.5%, and the government debt was 87.4% of GDP for the euro area and 80.8% for the EU. See News release of 22 October 2024.

Methods and definitions

According to Article 14 (1) of Council Regulation (EC) 479/2009, Eurostat publishes the actual government deficit and debt data for the application of the Protocol on the excessive deficit procedure, within three weeks after the reporting deadlines.

The Protocol on the excessive deficit procedure annexed to the EC Treaty, defines government deficit (surplus) as the net borrowing (net lending) of the whole general government sector (central government, state government, local government and social security funds). It is calculated according to national accounts concepts (European System of Accounts, ESA 2010). Government debt (commonly known as Maastricht or EDP debt) is the consolidated gross debt of the whole general government sector outstanding at the end of the year (at nominal value).

– for deficit / surplus and GDP data, the annual average exchange rate;

– for the stock of government debt, the end of year exchange rate.

General government total expenditure and revenue are reported to Eurostat under the ESA 2010 transmission programme. They cover non-financial transactions of general government, and include both current and capital transactions. For definitions, see Regulation (EU) No 549/2013 of the European Parliament and of the Council of 21 May 2013 on the European system of national and regional accounts in the European Union.

Intergovernmental lending

For the purpose of consolidation of general government debt in European aggregates and to provide users with information, Eurostat is collecting and publishing data on government loans to other EU governments, including those made through the European Financial Stability Facility (EFSF). For the years 2021 to 2024 the intergovernmental lending figures relate mainly to lending to Greece, Ireland and Portugal.

Reservations and amendments

The term “reservations” is defined in article 15 (1) of Council Regulation (EC) 479/2009. The Commission (Eurostat) expresses reservations when it has doubts on the quality of the reported data.

According to Article 15 (2) of Council Regulation (EC) 479/2009, the Commission (Eurostat) may amend actual data reported by Member States and provide the amended data and a justification of the amendment where there is evidence that actual data reported by Member States do not comply with the quality requirements (compliance with accounting rules, completeness, reliability, timeliness and consistency of statistical data).

Geographical information

Euro area (EA20): Belgium, Germany, Estonia, Ireland, Greece, Spain, France, Croatia, Italy, Cyprus, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Austria, Portugal, Slovenia, Slovakia and Finland.

European Union (EU27): Belgium, Bulgaria, Czechia, Denmark, Germany, Estonia, Ireland, Greece, Spain, France, Croatia, Italy, Cyprus, Latvia, Lithuania, Luxembourg, Hungary, Malta, the Netherlands, Austria, Poland, Portugal, Romania, Slovenia, Slovakia, Finland and Sweden.

For more information

For further information on the methodology of statistics reported under the excessive deficit procedure, please see the Eurostat publication “Manual on Government Deficit and Debt – Implementation of ESA 2010 – 2022 edition”, published in February 2023.

Note on main revisions: Eurostat publishes on its website a note containing specific explanations of the largest revisions in deficit and debt for 2021-2023 between the October 2024 and April 2025 notifications, as well as in GDP.

Background note and supplementary tables on government interventions to support financial institutions: Eurostat publishes supplementary tables by Member State on the impact of the government support to financial institutions on its website. Eurostat also publishes a background note providing further information on the supplementary tables, including summary tables for the EU and the euro area. Table 2 of the background note shows government deficit/surplus data for 2023 and 2024 excluding the impacts of government interventions to support financial institutions. It should be noted that this adjusted measure of government deficit/surplus is only intended to be an improvement in the presentation of data for users.

Stock of liabilities of trade credits and advances: Eurostat publishes on its website, as complementary information on government liabilities, data on trade credits and advances, as reported by Member States for the years 2021 to 2024. According to Council Regulation (EC) 479/2009, the liabilities in trade credits and advances of government units are not part of EDP debt.

Stock-flow adjustment: Eurostat also publishes a note on the stock-flow adjustment which presents the contribution of deficit/surplus as well as other relevant factors to the variation in the debt level.

Eurostat will also be releasing information on the underlying government sector accounts on the government finance and EDP statistics section on its website.

Share the release

Share component will be rendered here.

* Here the title * … * … * * Here the logo and notes * */ function tableConfiguration() { /** Retrieves the list of table elements (images) */ const tables = document.getElementsByTagName(‘table’); /** We go through the list of tables */ for (let table of tables) { /** We create a section to wrap the table */ let section = document.createElement(‘section’); /** Add table-wrapper class to section element */ section.classList.add(‘table-wrapper’); /** We create a caption element to place the title */ let caption = document.createElement(‘caption’); /** We create thead element to place the headers */ let tHead = document.createElement(‘thead’); /** We create a footer to place notes, datasource and logo */ let footer = document.createElement(‘footer’); /** Retrieves the tBody */ let tBody = table.tBodies[0]; /** Retrieves the table rows */ let rows = tBody.rows; let datalabels = []; let captionContent = []; /** Stores the indexes of the rows to be removed after processing the whole table */ let rowsToRemove = []; /** We go through the rows within the table and extract caption, headers and footnotes */ buildTable(rows, captionContent, datalabels, footer, rowsToRemove); deleteRows(table, rowsToRemove); addTableCaption(caption, captionContent); addTableHeaders(table, tHead, datalabels); wrapInSection(section, table, caption, tHead, tBody, footer); linkHeaders(table); } } /** * Builds a table with the expected format: adding caption, datalabels and footer * @param {*} rows – The table rows * @param {*} captionContent – The content of the caption (title) * @param {*} datalabels – The list of datalabels (table headers) * @param {*} footer – The footer element * @param {*} rowsToRemove – Array containing the index of the rows to be removed */ function buildTable(rows, captionContent, datalabels, footer, rowsToRemove) { let rowIndex = 0; for (let row of rows) { let cells = row.cells; /** We check the first cell in order to guess the cell type: th, td; and cell classes: title, datalabel… */ let firstCell = row.firstElementChild; /** If the th class name is title, we convert this th into a caption */ if (isCaption(firstCell)) { addCaption(cells, captionContent, rowIndex, rowsToRemove) } /** If the th class name is datalabel, we add the header to the tHead component */ else if (isDatalabel(firstCell)) { addDatalabels(row, datalabels, rowIndex, rowsToRemove); } /** If the th class name is title, we convert this th into a caption */ else if (isFooter(firstCell)) { addFooter(row, footer, rowIndex, rowsToRemove); } else { row.setAttribute(‘initial-position’, rowIndex); } rowIndex++; } } /** * Checks whether the given cell has the given tagName and className * @param {*} cell – The cell to be checked * @param {*} tagName – The tag name to be checked * @param {*} className – The class name to be checked * @returns true if the cell’s tagName and className matches the given ones, false otherwise */ function checkCell(cell, tagName, className) { return cell.tagName.toLowerCase() === tagName && cell.className.indexOf(className) > -1; } /** * Whether a cell is a caption (title) * @param {*} cell – The cell to be checked * @returns true if the cell is a caption, false otherwise */ function isCaption(cell) { return checkCell(cell, ‘th’, ‘title’); } /** * Whether a cell is a datalabel * @param {*} cell – The cell to be checked * @returns true if the cell is a datalabel, false otherwise */ function isDatalabel(cell) { return checkCell(cell, ‘th’, ‘datalabel’); } /** * Whether a cell is a vertical header * @param {*} cell – The cell to be checked * @returns true if the cell is a vertical header, false otherwise */ function isVerticalHeader(cell) { return checkCell(cell, ‘th’, ‘vertical-header’); } /** * Whether a cell is a footer * @param {*} cell – The cell to be checked * @returns true if the cell is a footer, false otherwise */ function isFooter(cell) { return checkCell(cell, ‘td’, ‘footer’); } /** * Adds the content of the caption cells: paragraphs * @param {*} cells – The cells belonging to the row * @param {*} captionContent – The content of the caption * @param {*} rowIndex – The index of current row * @param {*} rowsToRemove – Array containing the index of the rows to be removed */ function addCaption(cells, captionContent, rowIndex, rowsToRemove) { for (let cell of cells) { /** We must add all the Child Nodes of each th title Cell */ for (let childNode of cell.childNodes) { captionContent.push(childNode); } } /** We remove the row from within the tables as now it’s out in the caption */ rowsToRemove.push(rowIndex); } /** * Adds the row as a datalabel * @param {*} row – The current row * @param {*} datalabels – List of datalabels * @param {*} rowIndex – The index of current row * @param {*} rowsToRemove – Array containing the index of the rows to be removed */ function addDatalabels(row, datalabels, rowIndex, rowsToRemove) { datalabels.push(row); /** We remove the row from within the tables as now it’s out in the caption */ rowsToRemove.push(rowIndex); } /** * Adds the notes and logo * @param {*} row – The current row * @param {*} footer – The footer of the table * @param {*} rowIndex – The index of current row * @param {*} rowsToRemove – Array containing the index of the rows to be removed */ function addFooter(row, footer, rowIndex, rowsToRemove) { /** We create a div element for notes and logo */ const notes = document.createElement(‘div’); notes.classList.add(‘footer-element’, ‘notes’); /** We add the content to the new note element */ notes.innerHTML = row.firstElementChild.innerHTML; /** We create a footer to place notes, datasource and logo */ footer.appendChild(notes); /** We remove the row from within the tables as now it’s out in the footer */ rowsToRemove.push(rowIndex); } /** * Deletes the rows which data has been moved to either caption, tHead or footer * @param {*} table – The current table * @param {*} rowsToRemove – Array containing the index of the rows to be removed */ function deleteRows(table, rowsToRemove) { /** We go through the title rows and append them to the caption element */ for (let j = rowsToRemove.length – 1; j >= 0; j–) { table.deleteRow(rowsToRemove[j]); } } /** * Adds the caption to the table. * @param {*} caption – The caption dom element * @param {*} captionContent – The content of the caption */ function addTableCaption(caption, captionContent) { /** We go through the Caption Content and append the nodes to the caption element */ for (let node of captionContent) { caption.appendChild(node); } } /** * Adds the headers to the table * @param {*} table – The table to make sortable * @param {*} tHead – The thead dom element * @param {*} datalabels – The datalabels to be added (headers) */ function addTableHeaders(table, tHead, dataLabels) { let sortable = false; /** We go through the header rows and append them to the tHead element */ for (let dataLabelRow of dataLabels) { let cells = dataLabelRow.cells; for (let th of cells) { if (th.classList.contains(‘sortable’)) { sortable = true; let button = createNewSortButton(); th.appendChild(button); } } tHead.appendChild(dataLabelRow); } if (sortable) { table.classList.add(‘sortable’); } } function createNewSortButton() { // creates sort button const button = document.createElement(‘button’); button.classList.add(‘ecl-table__arrow’); // creates a generic svg element for the two arrows const svgIconUp = document.createElementNS(‘http://www.w3.org/2000/svg’, ‘svg’); svgIconUp.setAttribute(‘xml:space’, ‘preserve’); svgIconUp.setAttribute(‘viewBox’, ‘0 0 24 24’); svgIconUp.setAttribute(‘enable-background’, ‘new 0 0 24 24’); svgIconUp.setAttribute(‘focusable’, ‘false’); svgIconUp.setAttribute(‘aria-hidden’, ‘true’); svgIconUp.setAttribute(‘class’, ‘ecl-table__icon ecl-icon ecl-icon–m’); // adds path element of the arrow to the arrow svg const pathIconArrow = document.createElementNS(‘http://www.w3.org/2000/svg’, ‘path’); pathIconArrow.setAttribute(‘d’, ‘M7.4 13 11 9.4c.5-.5 1.4-.5 2 0l3.6 3.6c.9.9.2 2.4-1 2.4H8.4c-1.3 0-1.9-1.5-1-2.4’); svgIconUp.appendChild(pathIconArrow); // clones the generic arrow svg including the child path also const svgIconDown = svgIconUp.cloneNode(true); // seups the arrow directions to up and down by extra css classes svgIconUp.classList.add(‘ecl-table__icon-up’); svgIconDown.classList.add(‘ecl-table__icon-down’); // insert the two arrow svg elements into the button button.appendChild(svgIconUp); button.appendChild(svgIconDown); return button; } /** * Places all the elements in their places and wraps the table into a section. * @param {*} section – The section (dom element) which will wrap table and footer * @param {*} table – The table to be wrapped * @param {*} caption – The caption (dom element) to be added to the table * @param {*} tHead – The thead (dom element) to be added to the table * @param {*} tBody – The tbody (dom element) to be added to the table * @param {*} footer – The footer (dom element) to be added to the section */ function wrapInSection(section, table, caption, tHead, tBody, footer) { /** We insert caption and thead before tbody */ table.insertBefore(caption, tBody); table.insertBefore(tHead, tBody); /** We wrap the table into a section */ table.parentNode.insertBefore(section, table); section.appendChild(table); section.appendChild(footer); } /** * Adds ids and header attributes to link every cell to all related headers so that machines can correctly read the figures. * @param {*} table – The table to be wrapped */ function linkHeaders(table) { const headers = getHeaders(table.tHead); const tBody = table.tBodies ? table.tBodies[0] : null; addHeaderLinks(tBody, headers); } function getHeaders(tHead) { const headers = []; if (tHead) { let i = 0; for (let row of tHead.rows) { /** We add a new row in the headers array */ headers.push([]); /** Stores the header ids and colSpan so we can guess to which cells (td) we must add the headers */ let j = 0; for (const cell of row.cells) { cell.setAttribute(‘id’, ‘h_’ + i + ‘_’ + j); headers[i].push({ id: cell.id, colSpan: cell.colSpan ? cell.colSpan : 1 }); j++; } i++; } } return headers; } function addHeaderLinks(tBody, headers) { if (tBody) { let i = 0; for (let row of tBody.rows) { let j = 0; for (const cell of row.cells) { /** If the cell is a vertical header we add its id */ if (cell.className.indexOf(‘vertical-header’) > -1) { cell.setAttribute(‘id’, ‘vh_’ + i + ‘_’ + j); } const headerLinks = getHeaderLinks(headers, j, cell.colSpan, row.cells[0]); cell.setAttribute(‘headers’, headerLinks); j++; } i++; } } } /** * Retrieves the header (ths) ids in order to link them to a specific cell (td) * @param {*} rows – The rows containing all headers * @param {*} index – The index of the specific cell * @param {*} colSpan – The colspan of the specific cell * @param {*} firstCell – The first cell of the row. Used to reference possible vertical headers * @returns A string containing the list of header ids split by spaces */ function getHeaderLinks(rows, index, colSpan, firstCell) { /** It will contain the header ids */ let links = ”; /** We add the reference of the vertical header if there is */ if (index > 0 && firstCell.className.indexOf(‘vertical-header’) > -1) { links = firstCell.id; } /** We go through the list of header rows */ for (const headers of rows) { /** Accumulates the colspan of the checked headers */ let sumColSpan = 0; /** We go through the list of headers for the specific header row */ for (const header of headers) { /** We check that the index of the cell belongs to a specific column */ if (index >= sumColSpan && index chartObj.resize()).observe(chartDiv); } } /** * Customizes the chart by applying custom events, axis formats, tooltips, and axis labels. * @param option – The chart options object. */ function customChartOptions(option) { setClickableDatasourceLinks(option); setAxisFormatter(option); setTooltipFormatter(option); } /** * Attaches event handlers to a chart: ‘legendselectchanged’. * * @param {Chart} chart – The chart object. */ function addEventHandlers(chart) { /** Attach an event handler for the ‘legendselectchanged’ event */ chart.on(‘legendselectchanged’, (event) => { /** Call the onChartLegendSelected function with the event and chart object */ onChartLegendSelected(event, chart); }); } /** * Handles the legend selected changed event of the chart. * @param {any} event – The event object containing the selected legend items. * @param {any} chart – The chart object. */ function onChartLegendSelected(event, chart) { /** Get the selected legend items */ const selected = event.selected; /** Count the number of selected legend items */ const selectedCount = Object.values(selected).filter(Boolean).length; /** If all legend items are deselected, keep the selection on the last clicked item */ if (selectedCount === 0) { selected[event.name] = true; } /** Update the legend selection */ chart.setOption({ legend: { selected: selected } }); } /** * Attaches custom events to the provided option object. * * @param {object} option – The option object to attach custom events to. */ function setClickableDatasourceLinks(option) { /** If the table has datasource link */ if (option.graphic && option.graphic.length >= 3) { /** Attach an onclick event handler to the third element of the graphic array (datasource links) */ option.graphic[2].onclick = function (event) { /** If the element has a link defined in its style */ if (this.style?.link) { /** Open the link in a new tab/window */ window.open(this.style.link, ‘_blank’); } }; } } /** * Sets the default axis formatter for axis labels. * @param {object} option – The option object to update the axis formatter * */ function setAxisFormatter(option) { /** The default unit used in axis labels */ const defaultUnit = ‘%’; /** If the yAxis are used as values */ if (option.yAxis.type === ‘value’) { /** If the yAxis unit is not defined, set % as default */ option.yAxis.axisLabel.unit = option.yAxis.axisLabel.unit ? option.yAxis.axisLabel.unit : defaultUnit; /** If the yAxis label padding is not defined, set 15 as default suffix */ option.yAxis.axisLabel.padding = option.yAxis?.axisLabel?.padding ? option.yAxis.axisLabel.padding : 15; /** Use the custom formatter */ option.yAxis.axisLabel.formatter = (value) => customAxisFormatter(option.lang, value, option.yAxis.axisLabel.unit, parseInt(option.yAxis.axisLabel.decimals)); // Use the custom formatter } /** If the xAxis are used as values */ if (option.xAxis.type === ‘value’) { /** If the xAxis unit is not defined, set % as default */ option.xAxis.axisLabel.unit = option.xAxis.axisLabel.unit ? option.xAxis.axisLabel.unit : defaultUnit; /** Use the custom formatter */ option.xAxis.axisLabel.formatter = (value) => customAxisFormatter(option.lang, value, option.xAxis.axisLabel.unit, parseInt(option.xAxis.axisLabel.decimals)); } /** If xAxis type is category */ else if (option.xAxis.type === ‘category’) { boldCountries(option); } } /** * Formats a numeric value with a specified unit and decimal precision. * * @param {number} value – The numeric value to be formatted. * @param {string} unit – The unit to be appended to the formatted value. * @param {number} decimals – The number of decimal places to round the value to. * @returns {string} The formatted string representation of the value with unit. */ function customAxisFormatter(lang, value, unit, decimals) { /** * Check the language and format the value accordingly. * For French (fr) and German (de), use commas instead of dots. * For other languages (en), use the default format with dots. */ const formattedValue = lang === ‘fr’ || lang === ‘de’ ? `${value.toFixed(decimals).replace(‘.’, ‘,’)}${unit}` : `${value.toFixed(decimals)}${unit}`; return formattedValue; } /** * Enriches the x-axis labels with formatting based on certain values. * If EU and Euro Area are included, those must be written in bold * @remarks * This function enriches the x-axis labels with formatting based on certain values, such as making “EU” and “Euro Area” bold. * @param {object} option – The option object to set bold countries to. */ function boldCountries(option) { option.xAxis.axisLabel.formatter = function (v) { /** Convert input string to lowercase for case-insensitive comparison */ const lowerCaseV = v ? v.toLowerCase() : ”; /** Check for specific label values and format them accordingly, check for “EU” or “UE” */ if (lowerCaseV === “eu” || lowerCaseV === “ue”) { // return `{eu|${v}}`; } /** Check for “Euro Area”, “Euroraum”, or “Zone Euro” */ else if (lowerCaseV === “euro area” || lowerCaseV === “euroraum” || lowerCaseV === “zone euro”) { return `{euroArea|${v}}`; } return v; }; /** Set the rich property of the axis label to apply the bold formatting */ option.xAxis.axisLabel.rich = { eu: { fontWeight: “bold”, }, euroArea: { fontWeight: “bold” } }; } /** * Handles formatting the tooltip decimal convention in the graphic. * @remarks * This function formats the tooltip based on the language and decimal convention. * * @param {object} option – The option object to add custom tooltip. */ function setTooltipFormatter(option) { /** * Tooltip formatter for ECharts. * @param {object[]} params – Parameters for the tooltip formatter. * @param {string} params[].name – Name of the x-axis value. * @param {string} params[].seriesName – Name of the series. * @param {number} params[].value – Value of the data point. * @param {string} params[].color – Color of the series. * @param {string} ticket – Ticket for the callback. * @param {Function} callback – Callback function. * @returns {string} – Formatted tooltip content. */ option.tooltip.formatter = function (params, ticket, callback) { /** Retrieve the x-axis value for the tooltip */ const xAxisValue = params[0].name; /** If xAxisValue is empty, return null to hide the tooltip */ if (!xAxisValue) { return null; } /** Create the tooltip content container with a white background and padding */ let tooltipContent = ”; /** Add the x-axis value to the tooltip content */ /** @type {string} XAxis */ tooltipContent += ” + xAxisValue + ‘]]>

‘; /** Retrieve the order from the tooltip option */ const sortOrder = option.tooltip.order; /** Sort the ‘params’ array based on the ‘sortOrder’ parameter. */ switch (sortOrder) { /** Sort by series name in ascending order. */ case ‘seriesAsc’: params = params.sort((a, b) => a.seriesName.localeCompare(b.seriesName)); break; /** Sort by series name in descending order. */ case ‘seriesDesc’: params = params.sort((a, b) => b.seriesName.localeCompare(a.seriesName)); break; /** Sort by numerical value in ascending order. */ case ‘valueAsc’: params = params.sort((a, b) => parseFloat(a.value) – parseFloat(b.value)); break; /** Sort by numerical value in descending order. */ case ‘valueDesc’: params = params.sort((a, b) => parseFloat(b.value) – parseFloat(a.value)); break; /** Reverse the current order. */ case ‘reverse’: params.reverse(); break; default: break; } /** Iterate over each series in the tooltip parameters */ for (const param of params) { /** Retrieve the name and value of the current series */ let seriesName = param.seriesName; let value = param.value; /** Replace every specific apostrphe by simple one. */ seriesName = seriesName.replaceAll(“’”, “‘”); /** Convert the numeric value to its string representation. */ const strValue = String(value); /** Retrieve the axis used as value */ const axis = option.yAxis.type === ‘value’ ? option.yAxis : option.xAxis; /** Initialize the number of decimal places */ let decimals = option.tooltip.decimals; /** Check if decimals configuration is set to default and the value contains decimal places */ if (!decimals && strValue.indexOf(‘.’) > -1) { /** Calculate the number of decimal places */ decimals = strValue.substring(strValue.indexOf(‘.’), strValue.length – 1).length; } else { /** If there are no decimal places, format the value with 1 decimal place */ decimals = decimals || 1; /** Convert the value to a fixed-point notation string with a specified number of decimal places. */ value = Number(value).toFixed(decimals); } /** Convert -0 value to 0 with the specified or calculated number of decimal places.*/ if (Number(value) == -0) { value = (Number(value) + 0).toFixed(decimals); } /** Extract the unit from within the axis label */ const unit = axis.axisLabel.unit ? axis.axisLabel.unit : ”; /** Format the value using the appropriate number of decimal places */ if (isNaN(value)) { value = ‘N/A’; } else { value = Number(value).toLocaleString(option.lang ? option.lang : ‘en’, { minimumFractionDigits: decimals }) + unit; } /** Retrieve the color of the current series */ const color = param.color; /** * Add the series name and value to the tooltip content * Use a circle icon with the series color */ tooltipContent += ‘

‘ + ” + ” + ” + seriesName + ” + ” + ” + value + ” + ‘

‘; } /** Close the tooltip content container */ tooltipContent += ”; /** Return the formatted tooltip content */ return tooltipContent; } } /* * This content is licensed according to the W3C Software License at * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document * * File: sortable-table.js * * Desc: Adds sorting to a HTML data table that implements ARIA Authoring Practices */ class SortableTable { constructor(tableNode) { this.tableNode = tableNode; this.columnHeaders = tableNode.querySelectorAll(‘thead th.sortable’); this.sortColumns = []; for (let i = 0; i b.value ? -1 : 1; } } else if (isNumber) { return a.value – b.value; } else { return a.value

Subscribe to receive the latest Eurostat Euro indicators releases

{ if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { resolve(document.querySelector(selector)); observer.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); }); } waitForElm(‘div.chart’).then((elm) => { // Has to be run after cool-ngx-editor.js script that is tweeking the charts const elements = document.getElementsByClassName(“chart”); for (let i = 0; i < elements.length; i++) { let div = document.createElement('div'); div.id = "share-chart-" + i; div.style = "position: absolute; right: 0; z-index: 50;"; elements[i].prepend(div); let script = document.createElement('script'); script.type = "application/json"; let url = new URL(window.location.href); url.searchParams.set('item', 'chart'); url.searchParams.set('id', i); let code = '{"service": "sbkm", "version": "2.0", "popup": false, "icon": true, "more" : ["facebook", "x", "linkedin", "email"], "renderTo": "' + div.id + '", "to": ["more"], "target": true, "link": "' + url.href + '", "via": "EU_Eurostat", "title": "' + getJournalArticleTitle() + '"}'; try { script.appendChild(document.createTextNode(code)); } catch (e) { s.text = code; } elements[i].parentNode.insertBefore(script, elements[i].nextSibling); } }); // Add share button to tables $(document).ready(function() { // Has to be run after cool-ngx-editor.js script that is tweeking the tables const tables = document.getElementsByTagName("table"); for (let i = 0; i position) { await new Promise(r => setTimeout(r, 500)); // Wait a bit so that it doesn’t scroll too far allItems[position].scrollIntoView(true); } } });;}());]]>