diff --git a/CHANGELOG b/CHANGELOG
index d848223c3354482777be4ff30276f410997731a4..34f8c85ea3e60f94c369df663d4ca8dd1b2573b8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,8 @@ BornAgain-22.0, in preparation
   > GUI changes:
     * Examples DepthProfile, Transmission: flattened DepthProbeSimulation
   > Examples and documentation:
+  > Bug fixes:
+    * Fix intensity background (#328)
   > Internal refactoring:
     * Simplified coordinate names and units, now both in Scale::name (#487, #614)
     * Remove ICoordSystem and children; functionality provided by Frame
diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp
index 6417a82cce81380844eab720ed478ef969686427..557621905ab9358c60c6b7ddaf6b8c3a03917982 100644
--- a/GUI/Model/Device/InstrumentItems.cpp
+++ b/GUI/Model/Device/InstrumentItems.cpp
@@ -355,7 +355,7 @@ void ScanningFunctionality::readScanFrom(QXmlStreamReader* r)
 //  ************************************************************************************************
 
 SpecularInstrumentItem::SpecularInstrumentItem()
-    : ScanningFunctionality(1)
+    : ScanningFunctionality(1e6)
 {
 }
 
diff --git a/Sim/Simulation/DepthprobeSimulation.cpp b/Sim/Simulation/DepthprobeSimulation.cpp
index e24a6a81ec280c9f1bc5688d939c0a0be1e02d2c..df52d32e2ca226ed7d7b830a3351570942aee517 100644
--- a/Sim/Simulation/DepthprobeSimulation.cpp
+++ b/Sim/Simulation/DepthprobeSimulation.cpp
@@ -150,9 +150,6 @@ void DepthprobeSimulation::runComputation(const ReSample& re_sample, size_t i, d
     for (double& v : intensities)
         v *= intensity_factor;
 
-    if (background())
-        throw std::runtime_error("nonzero background is not supported by DepthprobeSimulation");
-
     const size_t N1 = m_z_axis->size();
     for (size_t j = 0; j < N1; ++j)
         m_cache[i * N1 + j] += intensities[j] * weight;
@@ -177,5 +174,8 @@ Datafield DepthprobeSimulation::packResult()
     std::vector<const Scale*> axes{m_scan->coordinateAxis()->clone(), m_z_axis->clone()};
     auto data = std::make_unique<Datafield>(std::move(axes), m_cache);
 
+    if (background())
+        throw std::runtime_error("nonzero background is not supported by DepthprobeSimulation");
+
     return {*data};
 }
diff --git a/Sim/Simulation/OffspecSimulation.cpp b/Sim/Simulation/OffspecSimulation.cpp
index 673e65e47d9fe9e0b23a12005807afd392316bb4..1c4625671c525d9cc7374485b7920dc10c6c000f 100644
--- a/Sim/Simulation/OffspecSimulation.cpp
+++ b/Sim/Simulation/OffspecSimulation.cpp
@@ -108,9 +108,6 @@ void OffspecSimulation::runComputation(const ReSample& re_sample, size_t i, doub
         intensity *= m_scan->intensity() * solid_angle / sin_alpha_i;
     }
 
-    if (background())
-        intensity = background()->addBackground(intensity);
-
     m_cache[i] += intensity * weight;
 
     progress().incrementDone(1);
@@ -130,14 +127,13 @@ size_t OffspecSimulation::nElements() const
 
 Datafield OffspecSimulation::packResult()
 {
-
     // update intensity map
     Datafield intensity_map({m_scan->coordinateAxis()->clone(), m_detector->axis(1).clone()});
     intensity_map.setAllTo(0.);
 
     size_t ny = m_detector->axis(1).size();
 
-    // Normalize, apply detector resolution and transfer detector image
+    // Apply detector resolution and transfer detector image
     for (size_t j = 0; j < m_scan->coordinateAxis()->size(); ++j) {
         Datafield detector_image({m_detector->axis(0).clone(), m_detector->axis(1).clone()});
         size_t N = detector_image.size();
@@ -146,6 +142,11 @@ Datafield OffspecSimulation::packResult()
         // TODO restore resolution m_detector->applyDetectorResolution(&detector_image);
         for (size_t i = 0; i < N; ++i)
             intensity_map[j * ny + i % ny] += detector_image[i];
+
+        if (background())
+            for (size_t i = 0; i < N; ++i)
+                intensity_map[j * ny + i % ny] =
+                    background()->addBackground(intensity_map[j * ny + i % ny]);
     }
 
     return {intensity_map};
diff --git a/Sim/Simulation/ScatteringSimulation.cpp b/Sim/Simulation/ScatteringSimulation.cpp
index 47047909b0b417cdb2b0e3dd705e0d046ec3dbc2..0366c05d0e2c9860a3e19a50847c93818cbc3123 100644
--- a/Sim/Simulation/ScatteringSimulation.cpp
+++ b/Sim/Simulation/ScatteringSimulation.cpp
@@ -100,9 +100,6 @@ void ScatteringSimulation::runComputation(const ReSample& re_sample, size_t i, d
         intensity *= m_beam->intensity() * solid_angle / sin_alpha_i;
     }
 
-    if (background())
-        intensity = background()->addBackground(intensity);
-
     m_cache[i] += intensity * weight;
 
     progress().incrementDone(1);
@@ -128,5 +125,10 @@ Datafield ScatteringSimulation::packResult()
         [&](const auto it) { result[it.roiIndex()] = m_cache[elementIndex++]; });
     m_detector->applyDetectorResolution(&result);
 
+    if (background())
+        m_detector->iterateOverNonMaskedPoints([&](const auto it) {
+            result[it.roiIndex()] = background()->addBackground(result[it.roiIndex()]);
+        });
+
     return result;
 }
diff --git a/Sim/Simulation/SpecularSimulation.cpp b/Sim/Simulation/SpecularSimulation.cpp
index d96f8985ac8f3f00caba8b3ca926af39e40b9c98..75c3d8451e7b9bce20bc4011507884d265d4bbe5 100644
--- a/Sim/Simulation/SpecularSimulation.cpp
+++ b/Sim/Simulation/SpecularSimulation.cpp
@@ -75,12 +75,7 @@ void SpecularSimulation::runComputation(const ReSample& re_sample, size_t iEleme
         }
     }
 
-    double intensity = refl * ele.footprint();
-
-    if (background())
-        intensity = background()->addBackground(intensity);
-
-    m_cache[iElement] += intensity * weight;
+    m_cache[iElement] += refl * ele.footprint() * weight;
 
     progress().incrementDone(1);
 }
@@ -104,6 +99,9 @@ Datafield SpecularSimulation::packResult()
         const SpecularElement& ele = m_eles.at(i);
         vec.at(ele.i_out()) += m_scan->intensity() * m_cache.at(i) * ele.weight();
     }
+    if (background())
+        for (size_t i = 0; i < m_scan->nScan(); i++)
+            vec[i] = background()->addBackground(vec[i]) / m_scan->intensity();
 
     Datafield data({m_scan->coordinateAxis()->clone()}, vec);
     return {data};
diff --git a/hugo/content/ref/sim/setup/bg/index.md b/hugo/content/ref/sim/setup/bg/index.md
index 1eff36a66cfe8c25cd0d74f76a33877e6e231c63..4d197c0d0ff83ad39779a114114a569239ffd7e4 100644
--- a/hugo/content/ref/sim/setup/bg/index.md
+++ b/hugo/content/ref/sim/setup/bg/index.md
@@ -1,8 +1,21 @@
 +++
-title = "Constant background"
+title = "Background"
 weight = 80
 +++
 
+### Poisson background
+
+To add a Poisson background to a `Simulation` instance, use
+
+```python
+bg = ba.PoissonBackground()
+simulation.setBackground(bg)
+```
+
+In this case, the output intensity is randomly distributed around the exact value with discrete Poisson statistics.
+
+The lower the intensity of the probing beam, the lower the signal-to-noise ratio.
+
 ### Constant background
 
 To add a constant background to a `Simulation` instance, use
@@ -12,6 +25,8 @@ bg = ba.ConstantBackground(1e3)
 simulation.setBackground(bg)
 ```
 
+Background is applied before the [specular simulation](/ref/sim/class/specular) is normalized, so the threshold value will also be divided by the probe beam intensity. 
+
 {{< galleryscg >}}
 {{< figscg src="/img/auto/scatter2d/ConstantBackground.png" width="450px" caption="Intensity image">}}
 {{< /galleryscg >}}