PennyLane
Install
Install

Related materials

  • Related contentA Game of Surface Codes: Large-Scale Quantum Computing with Lattice Surgery
  • Related contentModeling the toric code on a quantum computer
  • Related contentStabilizer codes for quantum error correction

Contents

  1. Introduction
  2. Stabilizers
  3. Logical operators: Z and X edges
  4. Quantum computation via lattice surgery
  5. Error correction
  6. Conclusion
  7. References
  8. About the author

Downloads

  • Download Python script
  • Download Notebook
  • View on GitHub
  1. Demos/
  2. Quantum Computing/
  3. Introducing the Surface Code

Introducing the Surface Code

Korbinian Kottmann

Korbinian Kottmann

Published: December 16, 2025. Last updated: January 21, 2026.

The surface code is the gold standard when it comes to quantum error correction (QEC). Despite its early inception in the 90s, it is still relevant in many modern quantum computing architectures today. During that timespan, it has evolved quite a bit. In this demo, we will give an overview of the inner workings of the surface code to perform quantum error correction. These principles are ubiquitous in modern QEC codes, so this demo should serve as a good starting point to get into QEC in 2026.

demos/_static/demo_thumbnails/large_demo_thumbnails/pennylane-demo-surface-code-large-thumbnail.png

Introduction

We are going to take a look at the planar, two-dimensional, rotated surface code. This is a modern variant of the Kitaev surface code [1] [2] and not to be confused with the toric code or one of the many other variants that generalize it.

The rotated surface code consists of alternating X (blue) and Z (orange) squares that make up a lattice. The so-called data qubits sit on the vertices (highlighted in pink). These will be the qubits that encode the quantum information of a \(d \times d\) surface code patch, that is making up a single logical qubit: (we will use \(d=5\) throughout for simplicity)

../../_images/surface_code_syndrome.png

We additionally have so-called syndrome qubits (in light gray) that sit in the middle of the squares. These syndrome qubits are used to continuously perform measurements on the surrounding data qubits in a non-destructive way. These measurements are called stabilizers and make up the backbone of almost all modern QEC codes. In the rotated surface code, they are alternating squares with a product of four \(X\) or \(Z\) operators. Additionally, there are weight-2 \(X\) and \(Z\) arches on the edges (more on that later).

../../_images/surface_code_with_stabilizers.png

These stabilizers on the data qubits are measured indirectly via the syndrome qubits. This is done by entangling the data qubits with the corresponding syndrome qubit and then measuring that (see Fig. 1 in [3] for the detailed circuits). The measurement result (\(\pm 1\)) of a stabilizer measurement indicates whether or not an error has occurred. A \(d \times d\) surface code qubit can detect up to \(d-1\) errors, and correct up to \(\left\lfloor \tfrac{d-1}{2} \right\rfloor\). When more errors occur, they may go unnoticed or get corrected in the wrong way, as we will see later.

In this demo, we are going to go into more detail and expand on each of these components. Before that, we want to stress the difference between the rotated surface code (left) to the original planar surface code (right):

../../_images/rotated.png

In the central image we see their correspondences. Note that the solid pink lines are merely a guide to the eye and do not represent physical connectivity. They are typically used in this way to discern face plaquette operators of \(Z\) stabilizers, and vertex or star operators of \(X\) stabilizers. They are very similar, but the rotated surface code effectively halves the required qubits from \(4d^2 - 4d + 1\) to \(2d^2-1\) for a given code-distance \(d\).

For the purpose of this demo, we shall refer to it just as the surface code.

Stabilizers

The surface code is a stabilizer code, which means that quantum information is encoded in the joint \(+1\) eigenspace of a set of commuting observables \(\mathcal{S}\) called stabilizers. These stabilizers \(S_i \in \mathcal{S}\) are faces of four or two \(Z\) or \(X\) observables, arranged in a checkerboard formation: (the stabilizer operators are their product)

../../_images/surface_code_with_stabilizers.png

All these stabilizers commute with each other - that is one of their defining properties. That all stabilizers in the surface code depicted here commute can be seen from the fact that generally two Pauli words commute iff they anticommute on an even number of sites. Take for example the most simple case, two sites [0, 1], such that we have \([X_0 X_1, Z_0 Z_1] = 0\).

The measurement outcome of such a stabilizer is binary \(\pm 1\) and we assume that the underlying quantum state \(|\psi\rangle\) that is encoded by the qubit of the surface code is in the so-called code (sub)space - the joint \(+1\) eigenspace of all stabilizer measurements. That means that the action of any stabilizer \(S_i \in \mathcal{S}\) on a state \(|\psi\rangle\) in the code space is equal to the identity, \(S_i |\psi\rangle = + 1 |\psi\rangle\).

By continuously measuring all stabilizers we can ensure that the state is not leaving the code space. If, however, we do measure \(-1\) somewhere, we know that an error has occurred. In that case, we need to perform error correction, which we are discussing later.

Logical operators: Z and X edges

You may have noticed that we have weight-2 stabilizers (arches) at the edges of our surface code patch. These are crucial for defining logical operators on the surface code patch.

Logical operators \(Z_L\) or \(X_L\) need to commute with all stabilizers so they don’t move our state outside the code space. At the same time, they must not be stabilizers (or products thereof) themselves. On top of that, they of course need to satisfy the fundamental anti-commutation relation \(X_L Z_L = -Z_L X_L\).

On the rotated surface code, a logical \(X_L\) operator is a string of measurements of data qubits that connects the two edges with \(X\) arches (left and right here). And vice versa for a logical \(Z_L\) operator, as indicated below.

Multiplying a logical operator by a stabilizer does not change the logical state, so the string on the right hand side is an equivalent logical operator (recall that \(Z^2=\mathbb{1}\)).

../../_images/Z_string.png

We can continue to deform the string to arrive at a logical \(Z_L\) operator that goes along the right edge.

../../_images/Z_edge.png

This is why the left and right edge are called \(Z\) edges, which may be confusing because they contain \(X\) arches. The opposite is true for the top and bottom \(X\) edges with \(Z\) arches.

These arches define the logical operators, but they are also crucial from a mathematical point of view and restrict our \(d \times d\) patch to exactly one logical qubit. That is because the number of encoded qubits \(k\) is given by the difference of data qubits \(n\) and independent stabilizers \(s\), so \(k = n - s\). For the \(5 \times 5\) patch we are considering, we have \(n=25\) data qubits and \(16\) weight-4 stabilizers. Together with the \(8\) arches we get \(k = 25 - 16 - 8 = 1\).

The arches are also important for coverage of all possible errors. E.g., if a \(X\) error occurred on the top left data qubit, only the top left \(Z\) arch would catch it.

Quantum computation via lattice surgery

There are different variants of how to perform quantum computation with the surface code. Braiding is an older approach [4], but most modern approaches use lattice surgery [6] [5]. The concept is relatively simple: To measure \(Z_L \otimes Z_L\) between two surface code qubits, simply connect them via their \(Z\) edge (lattice merging), perform \(d\) rounds of measuring all stabilizers, including the intermediary ones, and finally destructively measure in between the two patches to split them again (lattice splitting). The logical \(Z_L \otimes Z_L\) measurement is indirectly determined via the product of the stabilizers that have been measured during the intermediate rounds of error correction. Note that this is different from terminal measurements where data qubits are measured directly.

../../_images/lattice_surgery.png

This is important because most modern surface code constructions are targeting Pauli based computation, where all logical operations can be reduced to such Pauli product measurements.

In fact, in the Game of Surface Codes [7], a popular framework for thinking about fault tolerant quantum computers, we forget about everything but the \(X\) and \(Z\) edges of our qubit patches. This results in rectangular boxes with solid (\(Z\)) and dotted (\(X\)) edges. The same \(Z_L \otimes Z_L\) measurement from above can be portrayed as

../../_images/gosc.png

This diagram simply says, we measure qubits \(|q_1\rangle\) and \(|q_2\rangle\) along their \(Z\) edges via an intermediate auxiliary qubit region, indicated by the blue connection. So overall, this is just the joint measurement of \(Z_{q_1} \otimes Z_{q_2}\) via their \(Z\) edges.

Error correction

Let us first consider what actually happens if a single \(Z\) error occurs on one of the data qubits. The story works equivalently for \(X\) errors. Before the \(Z\) error, each stabilizer measurement returns \(+1\), confirming the underlying state is in the correct code space. Now let us assume the central data qubit experiences a \(Z\) error. The surrounding \(Z\) stabilizers are unaffected by it, but the two \(X\) stabilizers yield a \(-1\) measurement - a defect, indicated by \(-1\) on the stabilizer square.

../../_images/Z_error.png

The tricky part about error correction is that we are only ever given the information of the syndrome measurements and do not know what actually has physically happened. The same error syndromes could have also occurred due to, e.g., the following error pattern.

../../_images/unlikely_error.png

This scenario is, however, exponentially more unlikely. A common decoding algorithm is minimum-weight perfect matching (MWPM), that looks for the shortest (and thus most likely) error string and corrects that. In this scenario, the (by far) most likely error string is simply the central \(Z\) error.

Consider the following situation, where two different weight-2 error strings lead to the same error syndrome.

../../_images/same_weight_two.png

Here, both errors have the same minimum distance, so the choice for an MWPM decoder is ambiguous. Luckily, it does not matter which error we correct, as they are logically equivalent: they are the same error up to a \(Z\) stabilizer, in particular the one on the surface between the two defects.

In the following scenario, however, we will run into a real problem. Both error strings again lead to the same defect syndrome.

../../_images/fatal_error.png

Now, if the (less likely) error with three errors occurs, but we correct for the (more likely) second scenario, we overall perform a logical \(Z_L\) operation, and introduce an undetected error in our computation. This is a manifestation of the fact that a distance \(d=5\) rotated surface code qubit can only correct

\[t = \left\lfloor \frac{d-1}{2} \right\rfloor = 2\]

errors deterministically.

Intuitively, this makes sense. In a code with distance \(d\), logical operators are (at least) of weight \(d\). Logical operators change the logical state of the qubit without being noticed by any stabilizer. So the best we can do is detect errors up to \(d-1\). And we can only deterministically correct errors up to half the distance, because a wrong correction will make the total operation (error + correction) a logical operator that goes unnoticed.

Error correction is continuously performed during computation with one clock cycle corresponding to measuring all \(\mathcal{O}(d^2)\) stabilizers once. It is worth noting that the actual error correction typically happens in software, and no correction terms are actively applied. Instead, one typically tracks all detected errors based on their syndromes and then multiplies them retrospectively with the final measurement results at the end of the computation.

Conclusion

In this demo, we have learned about the basics of modern rotated surface codes from qubit definition, stabilizers, logical operators, computation to error decoding. Most modern quantum error correction codes such as qLDPC codes work under the same principles, so you should be well-prepared for continuing your QEC journey down this path.

References

[1]

A. Yu. Kitaev, “Fault-tolerant quantum computation by anyons”, arXiv:quant-ph/9707021, 1997

[2]

Sergey B. Bravyi, A. Yu. Kitaev, “Quantum codes on a lattice with boundary”, arXiv:quant-ph/9811052, 1998

[3]

Austin G. Fowler, Matteo Mariantoni, John M. Martinis, Andrew N. Cleland, “Surface codes: Towards practical large-scale quantum computation”, arXiv:1208.0928, 2012

[4]

Robert Raussendorf, Jim Harrington, Kovid Goyal, “Topological fault-tolerance in cluster state quantum computation”, arXiv:quant-ph/0703143, 2007

[5]

Dominic Horsman, Austin G. Fowler, Simon Devitt, Rodney Van Meter, “Surface code quantum computing by lattice surgery”, arXiv:1111.4022, 2011

[6]

Austin G. Fowler, Craig Gidney “Low overhead quantum computation using lattice surgery” arXiv:1808.06709, 2018.

[7]

Daniel Litinski “A Game of Surface Codes: Large-Scale Quantum Computing with Lattice Surgery” arXiv:1808.02892, 2018.

About the author

Korbinian Kottmann
Korbinian Kottmann

Korbinian Kottmann

Korbinian likes simulating quantum systems, whether it be via tensor network methods during his PhD, or with quantum computers at Xanadu. Currently, he works on quantum compilation to make simulation algorithms go brrr.

Share demo

Ask a question on the forum

Related Demos

A Game of Surface Codes: Large-Scale Quantum Computing with Lattice Surgery

Modeling the toric code on a quantum computer

Stabilizer codes for quantum error correction

Never miss a milestone

Get the latest quantum updates delivered to your inbox.

Join the list
PennyLane

PennyLane is an open-source quantum software platform for quantum computing, quantum machine learning, and quantum chemistry. Create meaningful quantum algorithms, from inspiration to implementation.

Created with ❤️ by Xanadu.

Research

  • Research

  • Performance

  • Hardware and simulators

  • Demos library

  • Compilation hub

  • Quantum datasets

Education

  • Teach

  • Learn

  • Codebook

  • Coding challenges

  • Videos

  • Glossary

Software

  • Install

  • Features

  • PennyLane documentation

  • Catalyst documentation

  • Development guide

  • How-to guides

  • API

  • GitHub


Xanadu

© Copyright 2026 | Xanadu | All rights reserved

TensorFlow, the TensorFlow logo and any related marks are trademarks of Google Inc.

Privacy policyTerms of serviceCookies policyCode of conduct