diff --git a/steps/StationAdder.cc b/steps/StationAdder.cc
index 1793a45e6046833e40b959e2589ae96b3a050d17..9a1cce166791f8dd9402c07d1e01518734703226 100644
--- a/steps/StationAdder.cc
+++ b/steps/StationAdder.cc
@@ -28,7 +28,6 @@
 #include "../base/FlagCounter.h"
 
 using casacore::ArrayColumn;
-using casacore::IPosition;
 using casacore::MPosition;
 using casacore::MVPosition;
 using casacore::Regex;
@@ -142,7 +141,7 @@ void StationAdder::updateInfo(const DPInfo& infoIn) {
     }
     // The superstation position is the average of its parts.
     newNames.push_back(iter->first);
-    newPosition *= 1. / parts.size();
+    newPosition *= 1.0 / parts.size();
     newPoss.push_back(MPosition(newPosition, MPosition::ITRF));
     itsParts.push_back(casacore::Vector<int>(parts));
     // Set the diameter of the new station by determining the
@@ -154,7 +153,7 @@ void StationAdder::updateInfo(const DPInfo& infoIn) {
           newPosition -
           MPosition::Convert(antennaPos[inx], MPosition::ITRF)().getValue();
       const casacore::Vector<double>& diff = mvdiff.getValue();
-      double dist = std::sqrt(std::accumulate(diff.cbegin(), diff.cend(), 0.,
+      double dist = std::sqrt(std::accumulate(diff.cbegin(), diff.cend(), 0.0,
                                               casacore::SumSqr<double>()));
       // Add the radius of the station used.
       maxdist = std::max(maxdist, dist + 0.5 * antennaDiam[inx]);
@@ -244,13 +243,6 @@ void StationAdder::updateInfo(const DPInfo& infoIn) {
   // Setup the UVW calculator (for new baselines).
   itsUVWCalc = std::make_unique<base::UVWCalculator>(
       infoIn.phaseCenter(), infoIn.arrayPos(), antennaPos);
-  // Size the buffer to cater for the new baselines.
-  const std::array<std::size_t, 3> shape{getInfo().nbaselines(),
-                                         getInfo().nchan(), getInfo().ncorr()};
-  itsBuf.ResizeData(shape);
-  itsBuf.ResizeFlags(shape);
-  itsBuf.ResizeWeights(shape);
-  itsBuf.ResizeUvw(getInfo().nbaselines());
 }
 
 void StationAdder::show(std::ostream& os) const {
@@ -279,38 +271,51 @@ void StationAdder::showTimings(std::ostream& os, double duration) const {
   os << " StationAdder " << itsName << '\n';
 }
 
-bool StationAdder::process(const DPBuffer& buf) {
+bool StationAdder::process(std::unique_ptr<base::DPBuffer> buffer) {
   itsTimer.start();
-  // Get the various data arrays.
-  const casacore::Array<casacore::Complex>& data = buf.GetCasacoreData();
-  const casacore::Array<bool>& flags = buf.GetCasacoreFlags();
-  const casacore::Array<float>& weights = buf.GetCasacoreWeights();
-  const casacore::Array<double>& uvws = buf.GetCasacoreUvw();
-  // Copy the data; only the first baselines will be filled.
-  std::copy(data.data(), data.data() + data.size(), itsBuf.GetData().data());
-  std::copy(flags.data(), flags.data() + flags.size(),
-            itsBuf.GetFlags().data());
-  std::copy(weights.data(), weights.data() + weights.size(),
-            itsBuf.GetWeights().data());
-  std::copy(uvws.data(), uvws.data() + uvws.size(), itsBuf.GetUvw().data());
+
+  // Resize of data buffers can be destructive, therefore we must:
+  // 1. Store the data locally.
+  // TODO(AST-1330): Avoid copying the data, e.g., using 'swap'.
+  const xt::xtensor<std::complex<float>, 3> input_data = buffer->GetData();
+  const xt::xtensor<bool, 3> input_flags = buffer->GetFlags();
+  const xt::xtensor<float, 3> input_weights = buffer->GetWeights();
+  const xt::xtensor<double, 2> input_uvws = buffer->GetUvw();
+  // 2. Resize the buffer to the new sizes that were set in our info object
+  const std::array<std::size_t, 3> new_shape{
+      getInfo().nbaselines(), getInfo().nchan(), getInfo().ncorr()};
+  buffer->ResizeData(new_shape);
+  buffer->ResizeFlags(new_shape);
+  buffer->ResizeWeights(new_shape);
+  buffer->ResizeUvw(getInfo().nbaselines());
+  // 3. Copy the data back into the resized buffer; only the existing baselines
+  // at the start will be filled the additional new baselines at the end will be
+  // empty.
+  std::copy_n(input_data.data(), input_data.size(), buffer->GetData().data());
+  std::copy_n(input_flags.data(), input_flags.size(),
+              buffer->GetFlags().data());
+  std::copy_n(input_weights.data(), input_weights.size(),
+              buffer->GetWeights().data());
+  std::copy_n(input_uvws.data(), input_uvws.size(), buffer->GetUvw().data());
+
   // Now calculate the data pointers of the new baselines.
-  unsigned int nrOldBL = data.shape()[2];
-  unsigned int nrcc = data.shape()[0] * data.shape()[1];
-  casacore::Complex* dataPtr = itsBuf.GetData().data() + data.size();
-  bool* flagPtr = itsBuf.GetFlags().data() + data.size();
-  float* wghtPtr = itsBuf.GetWeights().data() + data.size();
-  double* uvwPtr = itsBuf.GetUvw().data() + uvws.size();
+  unsigned int nrOldBL = input_data.shape()[0];
+  unsigned int nrcc = input_data.shape()[2] * input_data.shape()[1];
+  std::complex<float>* dataPtr = buffer->GetData().data() + input_data.size();
+  bool* flagPtr = buffer->GetFlags().data() + input_data.size();
+  float* wghtPtr = buffer->GetWeights().data() + input_data.size();
+  double* uvwPtr = buffer->GetUvw().data() + input_uvws.size();
   std::vector<unsigned int> npoints(nrcc);
-  std::vector<casacore::Complex> dataFlg(nrcc);
+  std::vector<std::complex<float>> dataFlg(nrcc);
   std::vector<float> wghtFlg(nrcc);
   // Loop over all new baselines.
   for (unsigned int i = 0; i < itsBufRows.size(); ++i) {
     // Clear the data for the new baseline.
     for (unsigned int k = 0; k < nrcc; ++k) {
-      dataPtr[k] = casacore::Complex();
+      dataPtr[k] = std::complex<float>();
       wghtPtr[k] = 0.;
       npoints[k] = 0;
-      dataFlg[k] = casacore::Complex();
+      dataFlg[k] = std::complex<float>();
       wghtFlg[k] = 0.;
     }
 
@@ -331,11 +336,11 @@ bool StationAdder::process(const DPBuffer& buf) {
       }
       blnr--;  // decrement because blnr+1 is stored in itsBufRows
       // Get pointers to the input baseline data.
-      const casacore::Complex* inDataPtr =
-          (itsBuf.GetData().data() + blnr * nrcc);
-      const bool* inFlagPtr = (itsBuf.GetFlags().data() + blnr * nrcc);
-      const float* inWghtPtr = (itsBuf.GetWeights().data() + blnr * nrcc);
-      const double* inUvwPtr = (itsBuf.GetUvw().data() + blnr * 3);
+      const std::complex<float>* inDataPtr = &buffer->GetData()(blnr, 0, 0);
+      const bool* inFlagPtr = &buffer->GetFlags()(blnr, 0, 0);
+      const float* inWghtPtr = &buffer->GetWeights()(blnr, 0, 0);
+      const double* inUvwPtr = &buffer->GetUvw()(blnr, 0);
+
       // Add the data, uvw, and weights if not flagged.
       // Write 4 loops to avoid having to test inside the loop.
       // Count the flagged points separately, so it can be used
@@ -428,8 +433,9 @@ bool StationAdder::process(const DPBuffer& buf) {
       }
     } else {
       unsigned int blnr = nrOldBL + i;
-      const std::array<double, 3> uvws = itsUVWCalc->getUVW(
-          getInfo().getAnt1()[blnr], getInfo().getAnt2()[blnr], buf.getTime());
+      const std::array<double, 3> uvws =
+          itsUVWCalc->getUVW(getInfo().getAnt1()[blnr],
+                             getInfo().getAnt2()[blnr], buffer->getTime());
       uvwPtr[0] = uvws[0];
       uvwPtr[1] = uvws[1];
       uvwPtr[2] = uvws[2];
@@ -440,10 +446,8 @@ bool StationAdder::process(const DPBuffer& buf) {
     wghtPtr += nrcc;
     uvwPtr += 3;
   }
-  itsBuf.setTime(buf.getTime());
-  itsBuf.setExposure(buf.getExposure());
   itsTimer.stop();
-  getNextStep()->process(itsBuf);
+  getNextStep()->process(std::move(buffer));
   return true;
 }
 
@@ -486,7 +490,7 @@ void StationAdder::addToMS(const string& msName) {
       stat = statCol(0);
     }
   }
-  casacore::Vector<double> offset(3, 0.);
+  casacore::Vector<double> offset(3, 0.0);
   // Put the data for each new antenna.
   for (unsigned int i = origNant; i < getInfo().antennaNames().size(); ++i) {
     antTab.addRow();
diff --git a/steps/StationAdder.h b/steps/StationAdder.h
index c12f1bde2d27bc6afd0bf8bc9ab0c6eb03407326..4d78f8968c99c8337c95c5b03b553075093a8408 100644
--- a/steps/StationAdder.h
+++ b/steps/StationAdder.h
@@ -61,7 +61,7 @@ class StationAdder : public Step {
   /// Process the data.
   /// It keeps the data.
   /// When processed, it invokes the process function of the next step.
-  bool process(const base::DPBuffer&) override;
+  bool process(std::unique_ptr<base::DPBuffer> buffer) override;
 
   /// Finish the processing of this step and subsequent steps.
   void finish() override;
@@ -94,7 +94,6 @@ class StationAdder : public Step {
                       casacore::Table& antTab);
 
   std::string itsName;
-  base::DPBuffer itsBuf;
   common::ParameterRecord itsStatRec;  ///< stations definitions
   std::vector<casacore::Vector<int>>
       itsParts;  ///< the stations in each superstation
diff --git a/steps/test/unit/tStationAdder.cc b/steps/test/unit/tStationAdder.cc
index bfb530bd859fc7b9a0cb28dd3d63a5f7a3b2790e..50478405a04d9d06af371acd263310fe7b39a1bf 100644
--- a/steps/test/unit/tStationAdder.cc
+++ b/steps/test/unit/tStationAdder.cc
@@ -8,6 +8,10 @@
 #include <casacore/casa/Arrays/ArrayLogical.h>
 #include <casacore/casa/BasicMath/Math.h>
 
+#include <xtensor/xcomplex.hpp>
+#include <xtensor/xio.hpp>
+#include <xtensor/xview.hpp>
+
 #include <boost/test/unit_test.hpp>
 #include <boost/test/data/test_case.hpp>
 
@@ -33,7 +37,8 @@ BOOST_AUTO_TEST_SUITE(stationadder)
 // It can be used with different nr of times, channels, etc.
 class TestInput : public dp3::steps::MockInput {
  public:
-  TestInput(int ntime, int nbl, int nchan, int ncorr)
+  TestInput(std::size_t ntime, std::size_t nbl, std::size_t nchan,
+            std::size_t ncorr)
       : itsCount(0),
         itsNTime(ntime),
         itsNBl(nbl),
@@ -47,7 +52,7 @@ class TestInput : public dp3::steps::MockInput {
     vector<int> ant2(nbl);
     int st1 = 0;
     int st2 = 0;
-    for (int i = 0; i < nbl; ++i) {
+    for (std::size_t i = 0; i < nbl; ++i) {
       ant1[i] = st1;
       ant2[i] = st2;
       if (++st2 == 4) {
@@ -85,44 +90,47 @@ class TestInput : public dp3::steps::MockInput {
     antPos[3] = casacore::MPosition(
         casacore::Quantum<casacore::Vector<double>>(vals, "m"),
         casacore::MPosition::ITRF);
-    vector<double> antDiam(4, 70.);
+    vector<double> antDiam(4, 70.0);
     info().setAntennas(antNames, antDiam, antPos, ant1, ant2);
     // Define the frequencies.
-    std::vector<double> chanWidth(nchan, 1000000.);
+    std::vector<double> chanWidth(nchan, 1000000.0);
     std::vector<double> chanFreqs;
-    for (int i = 0; i < nchan; i++) {
-      chanFreqs.push_back(10500000. + i * 1000000.);
+    for (std::size_t i = 0; i < nchan; i++) {
+      chanFreqs.push_back(10500000.0 + i * 1000000.0);
     }
     info().setChannels(std::move(chanFreqs), std::move(chanWidth));
   }
 
  private:
-  bool process(const DPBuffer&) override {
+  bool process(std::unique_ptr<DPBuffer>) override {
     // Stop when all times are done.
     if (itsCount == itsNTime) {
       return false;
     }
-    casacore::Cube<casacore::Complex> data(itsNCorr, itsNChan, itsNBl);
+
+    const std::array<std::size_t, 3> data_shape{itsNBl, itsNChan, itsNCorr};
+
+    xt::xtensor<std::complex<float>, 3> data(data_shape);
     for (int i = 0; i < int(data.size()); ++i) {
-      data.data()[i] =
-          casacore::Complex(i + itsCount * 10, i - 10 + itsCount * 6);
+      data[i] = std::complex<float>(i + itsCount * 10.0f,
+                                    i - 10.0f + itsCount * 6.0f);
     }
     casacore::Cube<float> weights(itsNCorr, itsNChan, itsNBl);
     indgen(weights, 0.5f, 0.01f);
     casacore::Matrix<double> uvw(3, itsNBl);
-    for (int i = 0; i < itsNBl; ++i) {
+    for (std::size_t i = 0; i < itsNBl; ++i) {
       uvw(0, i) = 1 + itsCount + i;
       uvw(1, i) = 2 + itsCount + i;
       uvw(2, i) = 3 + itsCount + i;
     }
     DPBuffer buf;
     buf.setTime(itsCount * 30 + 4472025740.0);
-    buf.setData(data);
+    buf.ResizeData(data_shape);
+    buf.GetData() = data;
     buf.setWeights(weights);
     buf.setUVW(uvw);
-    casacore::Cube<bool> flags(data.shape());
-    flags = false;
-    buf.setFlags(flags);
+    buf.ResizeFlags(data_shape);
+    buf.GetFlags().fill(false);
     getNextStep()->process(buf);
     ++itsCount;
     return true;
@@ -133,13 +141,14 @@ class TestInput : public dp3::steps::MockInput {
     // Do nothing / keep the info set in the constructor.
   }
 
-  int itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
+  std::size_t itsCount, itsNTime, itsNBl, itsNChan, itsNCorr;
 };
 
 // Class to check result of TestInput run by test1.
 class TestOutput : public dp3::steps::test::ThrowStep {
  public:
-  TestOutput(int ntime, int nbl, int nchan, int ncorr, bool sumauto)
+  TestOutput(int ntime, std::size_t nbl, std::size_t nchan, std::size_t ncorr,
+             bool sumauto)
       : itsCount(0),
         itsNTime(ntime),
         itsNBl(nbl),
@@ -148,27 +157,27 @@ class TestOutput : public dp3::steps::test::ThrowStep {
         itsSumAuto(sumauto) {}
 
  private:
-  void addData(casacore::Cube<casacore::Complex>& to,
-               const casacore::Cube<casacore::Complex>& from, int bl) {
-    to += from(casacore::IPosition(3, 0, 0, bl),
-               casacore::IPosition(3, to.nrow() - 1, to.ncolumn() - 1, bl));
+  void addData(xt::xtensor<std::complex<float>, 2>& to,
+               const xt::xtensor<std::complex<float>, 3>& from, int bl) {
+    to += xt::view(from, bl, xt::all(), xt::all());
   }
-  void addConjData(casacore::Cube<casacore::Complex>& to,
-                   const casacore::Cube<casacore::Complex>& from, int bl) {
-    to +=
-        conj(from(casacore::IPosition(3, 0, 0, bl),
-                  casacore::IPosition(3, to.nrow() - 1, to.ncolumn() - 1, bl)));
+  void addConjData(xt::xtensor<std::complex<float>, 2>& to,
+                   const xt::xtensor<std::complex<float>, 3>& from, int bl) {
+    to += xt::conj(xt::view(from, bl, xt::all(), xt::all()));
   }
-  bool process(const DPBuffer& buf) override {
-    casacore::Cube<casacore::Complex> data(itsNCorr, itsNChan, itsNBl);
+  bool process(std::unique_ptr<DPBuffer> buffer) override {
+    const std::array<std::size_t, 3> shape{itsNBl, itsNChan, itsNCorr};
+    xt::xtensor<std::complex<float>, 3> data(shape);
+
     for (int i = 0; i < int(data.size()); ++i) {
-      data.data()[i] =
-          casacore::Complex(i + itsCount * 10, i - 10 + itsCount * 6);
+      data[i] = std::complex<float>(i + itsCount * 10, i - 10 + itsCount * 6);
     }
     casacore::Cube<float> weights(itsNCorr, itsNChan, itsNBl);
     indgen(weights, 0.5f, 0.01f);
-    casacore::Cube<casacore::Complex> databl0(itsNCorr, itsNChan, 1);
-    casacore::Cube<casacore::Complex> databl1(itsNCorr, itsNChan, 1);
+    xt::xtensor<std::complex<float>, 2> databl0(
+        std::array<std::size_t, 2>{itsNChan, itsNCorr});
+    xt::xtensor<std::complex<float>, 2> databl1(
+        std::array<std::size_t, 2>{itsNChan, itsNCorr});
     // "{ns:[rs01.s01, rs02.s01, cs01.s02]}" was given resulting in 2 new
     // baselines (ns-ns and cs01.s01-ns).
     // Thus adding the baselines below.
@@ -195,39 +204,43 @@ class TestOutput : public dp3::steps::test::ThrowStep {
     addConjData(databl1, data, 2);
     addConjData(databl1, data, 6);
     addConjData(databl1, data, 14);
-    casacore::Matrix<double> uvw(3, itsNBl);
-    for (int i = 0; i < itsNBl; ++i) {
-      uvw(0, i) = 1 + itsCount + i;
-      uvw(1, i) = 2 + itsCount + i;
-      uvw(2, i) = 3 + itsCount + i;
+    xt::xtensor<double, 2> uvw(std::array<std::size_t, 2>{itsNBl, 3});
+    for (std::size_t i = 0; i < itsNBl; ++i) {
+      uvw(i, 0) = 1 + itsCount + i;
+      uvw(i, 1) = 2 + itsCount + i;
+      uvw(i, 2) = 3 + itsCount + i;
     }
-    casacore::IPosition end(3, itsNCorr - 1, itsNChan - 1, itsNBl - 1);
-    BOOST_CHECK(
-        allEQ(buf.GetCasacoreData()(casacore::IPosition(3, 0), end), data));
-    BOOST_CHECK_EQUAL(buf.GetCasacoreFlags().shape(),
-                      casacore::IPosition(3, itsNCorr, itsNChan, itsNBl + 2));
-    BOOST_CHECK(allEQ(buf.GetCasacoreFlags(), false));
-    BOOST_CHECK(allEQ(buf.GetCasacoreWeights()(casacore::IPosition(3, 0), end),
-                      weights));
-    BOOST_CHECK(
-        allEQ(buf.GetCasacoreUvw()(casacore::IPosition(2, 0),
-                                   casacore::IPosition(2, 2, itsNBl - 1)),
-              uvw));
+
+    auto xt_weights = aocommon::xt::CreateSpan(
+        weights.data(),
+        std::array{static_cast<std::size_t>(weights.shape()[2]),
+                   static_cast<std::size_t>(weights.shape()[1]),
+                   static_cast<std::size_t>(weights.shape()[0])});
+
+    BOOST_TEST(data == xt::view(buffer->GetData(), xt::range(0, itsNBl),
+                                xt::all(), xt::all()));
+    BOOST_TEST(buffer->GetFlags().shape() ==
+                   (std::array<std::size_t, 3>{itsNBl + 2, itsNChan, itsNCorr}),
+               boost::test_tools::per_element());
+    BOOST_CHECK(!xt::any(buffer->GetFlags()));
+    BOOST_TEST(xt_weights == xt::view(buffer->GetWeights(),
+                                      xt::range(0, itsNBl), xt::all(),
+                                      xt::all()));
+    BOOST_TEST(uvw ==
+               xt::view(buffer->GetUvw(), xt::range(0, itsNBl), xt::all()));
+
     // Now check data of new baselines.
-    end[2] = itsNBl;
-    BOOST_CHECK(allNear(
-        buf.GetCasacoreData()(casacore::IPosition(3, 0, 0, itsNBl), end),
-        databl0 / weight, 1e-5));
-    BOOST_CHECK(allNear(
-        buf.GetCasacoreWeights()(casacore::IPosition(3, 0, 0, itsNBl), end),
-        weight, 1e-5));
-    end[2] = itsNBl + 1;
-    BOOST_CHECK(allNear(
-        buf.GetCasacoreData()(casacore::IPosition(3, 0, 0, itsNBl + 1), end),
-        databl1 / 6.f, 1e-5));
-    BOOST_CHECK(allNear(
-        buf.GetCasacoreWeights()(casacore::IPosition(3, 0, 0, itsNBl + 1), end),
-        6.f, 1e-5));
+    BOOST_CHECK(
+        xt::allclose(xt::view(buffer->GetData(), itsNBl, xt::all(), xt::all()),
+                     (databl0 / weight)));
+    BOOST_CHECK(xt::allclose(
+        xt::view(buffer->GetWeights(), itsNBl, xt::all(), xt::all()), weight));
+    BOOST_CHECK(xt::allclose(
+        xt::view(buffer->GetData(), itsNBl + 1, xt::all(), xt::all()),
+        (databl1 / 6.0f)));
+    BOOST_CHECK(xt::allclose(
+        xt::view(buffer->GetWeights(), itsNBl + 1, xt::all(), xt::all()),
+        6.0f));
     itsCount++;
     return true;
   }
@@ -247,9 +260,11 @@ class TestOutput : public dp3::steps::test::ThrowStep {
     BOOST_CHECK_EQUAL(int(infoIn.antennaPos().size()), 5);
     BOOST_CHECK_EQUAL(infoIn.antennaNames()[4], "ns");
     casacore::Vector<double> pos1(infoIn.antennaPos()[4].getValue().getValue());
-    BOOST_CHECK(casacore::near(pos1[0], (3828763. + 3828746. + 3828713.) / 3));
-    BOOST_CHECK(casacore::near(pos1[1], (442449. + 442592. + 442878.) / 3));
-    BOOST_CHECK(casacore::near(pos1[2], (5064923. + 5064924. + 5064926.) / 3));
+    BOOST_CHECK(
+        casacore::near(pos1[0], (3828763.0 + 3828746.0 + 3828713.0) / 3));
+    BOOST_CHECK(casacore::near(pos1[1], (442449.0 + 442592.0 + 442878.0) / 3));
+    BOOST_CHECK(
+        casacore::near(pos1[2], (5064923.0 + 5064924.0 + 5064926.0) / 3));
     // Check diam.
     double d1 = sqrt((pos1[0] - 3828763) * (pos1[0] - 3828763) +
                      (pos1[1] - 442449) * (pos1[1] - 442449) +
@@ -265,7 +280,7 @@ class TestOutput : public dp3::steps::test::ThrowStep {
   }
 
   int itsCount;
-  int itsNTime, itsNBl, itsNChan, itsNCorr;
+  std::size_t itsNTime, itsNBl, itsNChan, itsNCorr;
   bool itsSumAuto;
 };