diff --git a/src/query/interpret/frame.hpp b/src/query/interpret/frame.hpp
index eab69898c..4f4617b1f 100644
--- a/src/query/interpret/frame.hpp
+++ b/src/query/interpret/frame.hpp
@@ -7,6 +7,7 @@
 #include "query/frontend/semantic/symbol_table.hpp"
 #include "query/typed_value.hpp"
 #include "utils/memory.hpp"
+#include "utils/pmr/vector.hpp"
 
 namespace query {
 
@@ -43,7 +44,7 @@ class Frame {
 
  private:
   int64_t size_;
-  utils::AVector<TypedValue> elems_;
+  utils::pmr::vector<TypedValue> elems_;
 };
 
 }  // namespace query
diff --git a/src/query/path.hpp b/src/query/path.hpp
index 81fa0788c..89b288c97 100644
--- a/src/query/path.hpp
+++ b/src/query/path.hpp
@@ -8,6 +8,7 @@
 #include "storage/edge_accessor.hpp"
 #include "storage/vertex_accessor.hpp"
 #include "utils/memory.hpp"
+#include "utils/pmr/vector.hpp"
 
 namespace query {
 
@@ -167,9 +168,9 @@ class Path {
 
  private:
   // Contains all the vertices in the path.
-  std::vector<VertexAccessor, utils::Allocator<VertexAccessor>> vertices_;
+  utils::pmr::vector<VertexAccessor> vertices_;
   // Contains all the edges in the path (one less then there are vertices).
-  std::vector<EdgeAccessor, utils::Allocator<EdgeAccessor>> edges_;
+  utils::pmr::vector<EdgeAccessor> edges_;
 };
 
 }  // namespace query
diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp
index 6bd77ba18..5b3265f78 100644
--- a/src/query/plan/operator.cpp
+++ b/src/query/plan/operator.cpp
@@ -27,6 +27,9 @@
 #include "utils/algorithm.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/hashing/fnv.hpp"
+#include "utils/pmr/unordered_map.hpp"
+#include "utils/pmr/unordered_set.hpp"
+#include "utils/pmr/vector.hpp"
 
 // macro for the default implementation of LogicalOperator::Accept
 // that accepts the visitor and visits it's input_ operator
@@ -667,7 +670,7 @@ auto ExpandFromVertex(const VertexAccessor &vertex,
   };
 
   // prepare a vector of elements we'll pass to the itertools
-  utils::AVector<decltype(wrapper(direction, vertex.in()))> chain_elements(
+  utils::pmr::vector<decltype(wrapper(direction, vertex.in()))> chain_elements(
       memory);
 
   if (direction != EdgeAtom::Direction::OUT && vertex.in_degree() > 0) {
@@ -752,9 +755,9 @@ class ExpandVariableCursor : public Cursor {
       ExpandFromVertex(std::declval<VertexAccessor>(), EdgeAtom::Direction::IN,
                        self_.common_.edge_types, utils::NewDeleteResource()));
 
-  utils::AVector<ExpandEdges> edges_;
+  utils::pmr::vector<ExpandEdges> edges_;
   // an iterator indicating the position in the corresponding edges_ element
-  utils::AVector<decltype(edges_.begin()->begin())> edges_it_;
+  utils::pmr::vector<decltype(edges_.begin()->begin())> edges_it_;
 
   /**
    * Helper function that Pulls from the input vertex and
@@ -811,9 +814,8 @@ class ExpandVariableCursor : public Cursor {
   }
 
   // Helper function for appending an edge to the list on the frame.
-  void AppendEdge(
-      const EdgeAccessor &new_edge,
-      std::vector<TypedValue, utils::Allocator<TypedValue>> *edges_on_frame) {
+  void AppendEdge(const EdgeAccessor &new_edge,
+                  utils::pmr::vector<TypedValue> *edges_on_frame) {
     // We are placing an edge on the frame. It is possible that there already
     // exists an edge on the frame for this level. If so first remove it.
     DCHECK(edges_.size() > 0) << "Edges are empty";
@@ -987,17 +989,14 @@ class STShortestPathCursor : public query::plan::Cursor {
   const ExpandVariable &self_;
   UniqueCursorPtr input_cursor_;
 
-  using VertexEdgeMapT = std::unordered_map<
-      VertexAccessor, std::optional<EdgeAccessor>, std::hash<VertexAccessor>,
-      std::equal_to<>,
-      utils::Allocator<
-          std::pair<const VertexAccessor, std::optional<EdgeAccessor>>>>;
+  using VertexEdgeMapT =
+      utils::pmr::unordered_map<VertexAccessor, std::optional<EdgeAccessor>>;
 
   void ReconstructPath(const VertexAccessor &midpoint,
                        const VertexEdgeMapT &in_edge,
                        const VertexEdgeMapT &out_edge, Frame *frame,
                        utils::MemoryResource *pull_memory) {
-    utils::AVector<TypedValue> result(pull_memory);
+    utils::pmr::vector<TypedValue> result(pull_memory);
     auto last_vertex = midpoint;
     while (true) {
       const auto &last_edge = in_edge.at(last_vertex);
@@ -1049,13 +1048,13 @@ class STShortestPathCursor : public query::plan::Cursor {
     auto *pull_memory = evaluator->GetMemoryResource();
     // Holds vertices at the current level of expansion from the source
     // (sink).
-    utils::AVector<VertexAccessor> source_frontier(pull_memory);
-    utils::AVector<VertexAccessor> sink_frontier(pull_memory);
+    utils::pmr::vector<VertexAccessor> source_frontier(pull_memory);
+    utils::pmr::vector<VertexAccessor> sink_frontier(pull_memory);
 
     // Holds vertices we can expand to from `source_frontier`
     // (`sink_frontier`).
-    utils::AVector<VertexAccessor> source_next(pull_memory);
-    utils::AVector<VertexAccessor> sink_next(pull_memory);
+    utils::pmr::vector<VertexAccessor> source_next(pull_memory);
+    utils::pmr::vector<VertexAccessor> sink_next(pull_memory);
 
     // Maps each vertex we visited expanding from the source (sink) to the
     // edge used. Necessary for path reconstruction.
@@ -1279,7 +1278,7 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
 
       // create the frame value for the edges
       auto *pull_memory = context.evaluation_context.memory;
-      utils::AVector<TypedValue> edge_list(pull_memory);
+      utils::pmr::vector<TypedValue> edge_list(pull_memory);
       edge_list.emplace_back(expansion.first);
       auto last_vertex = expansion.second;
       while (true) {
@@ -1330,14 +1329,11 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
   // maps vertices to the edge they got expanded from. it is an optional
   // edge because the root does not get expanded from anything.
   // contains visited vertices as well as those scheduled to be visited.
-  std::unordered_map<VertexAccessor, std::optional<EdgeAccessor>,
-                     std::hash<VertexAccessor>, std::equal_to<>,
-                     utils::Allocator<std::pair<const VertexAccessor,
-                                                std::optional<EdgeAccessor>>>>
+  utils::pmr::unordered_map<VertexAccessor, std::optional<EdgeAccessor>>
       processed_;
   // edge/vertex pairs we have yet to visit, for current and next depth
-  utils::AVector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_current_;
-  utils::AVector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_next_;
+  utils::pmr::vector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_current_;
+  utils::pmr::vector<std::pair<EdgeAccessor, VertexAccessor>> to_visit_next_;
 };
 
 class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
@@ -1490,7 +1486,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
         auto last_vertex = current_vertex;
         auto last_depth = current_depth;
         auto *pull_memory = context.evaluation_context.memory;
-        utils::AVector<TypedValue> edge_list(pull_memory);
+        utils::pmr::vector<TypedValue> edge_list(pull_memory);
         while (true) {
           // Origin_vertex must be in previous.
           const auto &previous_edge =
@@ -1553,23 +1549,17 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
   };
 
   // Maps vertices to weights they got in expansion.
-  std::unordered_map<
-      std::pair<VertexAccessor, int>, TypedValue, WspStateHash, std::equal_to<>,
-      utils::Allocator<
-          std::pair<const std::pair<VertexAccessor, int>, TypedValue>>>
+  utils::pmr::unordered_map<std::pair<VertexAccessor, int>, TypedValue,
+                            WspStateHash>
       total_cost_;
 
   // Maps vertices to edges used to reach them.
-  std::unordered_map<std::pair<VertexAccessor, int>,
-                     std::optional<EdgeAccessor>, WspStateHash, std::equal_to<>,
-                     utils::Allocator<std::pair<
-                         const std::pair<VertexAccessor, int>, TypedValue>>>
+  utils::pmr::unordered_map<std::pair<VertexAccessor, int>,
+                            std::optional<EdgeAccessor>, WspStateHash>
       previous_;
 
   // Keeps track of vertices for which we yielded a path already.
-  std::unordered_set<VertexAccessor, std::hash<VertexAccessor>, std::equal_to<>,
-                     utils::Allocator<VertexAccessor>>
-      yielded_vertices_;
+  utils::pmr::unordered_set<VertexAccessor> yielded_vertices_;
 
   // Priority queue comparator. Keep lowest weight on top of the queue.
   class PriorityQueueComparator {
@@ -1584,7 +1574,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
 
   std::priority_queue<
       std::tuple<double, int, VertexAccessor, std::optional<EdgeAccessor>>,
-      utils::AVector<
+      utils::pmr::vector<
           std::tuple<double, int, VertexAccessor, std::optional<EdgeAccessor>>>,
       PriorityQueueComparator>
       pq_;
@@ -1829,7 +1819,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, ExecutionContext &context) {
   // collect expressions results so edges can get deleted before vertices
   // this is necessary because an edge that gets deleted could block vertex
   // deletion
-  utils::AVector<TypedValue> expression_results(pull_memory);
+  utils::pmr::vector<TypedValue> expression_results(pull_memory);
   expression_results.reserve(self_.expressions_.size());
   for (Expression *expression : self_.expressions_) {
     expression_results.emplace_back(expression->Accept(evaluator));
@@ -2291,7 +2281,7 @@ class AccumulateCursor : public Cursor {
     // cache all the input
     if (!pulled_all_input_) {
       while (input_cursor_->Pull(frame, context)) {
-        std::vector<TypedValue, utils::Allocator<TypedValue>> row(
+        utils::pmr::vector<TypedValue> row(
             cache_.get_allocator().GetMemoryResource());
         row.reserve(self_.symbols_.size());
         for (const Symbol &symbol : self_.symbols_)
@@ -2327,10 +2317,7 @@ class AccumulateCursor : public Cursor {
  private:
   const Accumulate &self_;
   const UniqueCursorPtr input_cursor_;
-  std::vector<
-      std::vector<TypedValue, utils::Allocator<TypedValue>>,
-      utils::Allocator<std::vector<TypedValue, utils::Allocator<TypedValue>>>>
-      cache_;
+  utils::pmr::vector<utils::pmr::vector<TypedValue>> cache_;
   decltype(cache_.begin()) cache_it_ = cache_.begin();
   bool pulled_all_input_{false};
 };
@@ -2444,12 +2431,12 @@ class AggregateCursor : public Cursor {
 
     // how many input rows have been aggregated in respective values_ element so
     // far
-    std::vector<int, utils::Allocator<int>> counts_;
+    utils::pmr::vector<int> counts_;
     // aggregated values. Initially Null (until at least one input row with a
     // valid value gets processed)
-    std::vector<TypedValue, utils::Allocator<TypedValue>> values_;
+    utils::pmr::vector<TypedValue> values_;
     // remember values.
-    std::vector<TypedValue, utils::Allocator<TypedValue>> remember_;
+    utils::pmr::vector<TypedValue> remember_;
   };
 
   const Aggregate &self_;
@@ -2457,17 +2444,13 @@ class AggregateCursor : public Cursor {
   // storage for aggregated data
   // map key is the vector of group-by values
   // map value is an AggregationValue struct
-  std::unordered_map<
-      std::vector<TypedValue, utils::Allocator<TypedValue>>, AggregationValue,
-      // use FNV collection hashing specialized for a vector of TypedValues
-      utils::FnvCollection<
-          std::vector<TypedValue, utils::Allocator<TypedValue>>, TypedValue,
-          TypedValue::Hash>,
-      // custom equality
-      TypedValueVectorEqual,
-      utils::Allocator<
-          std::pair<const std::vector<TypedValue, utils::Allocator<TypedValue>>,
-                    AggregationValue>>>
+  utils::pmr::unordered_map<utils::pmr::vector<TypedValue>, AggregationValue,
+                            // use FNV collection hashing specialized for a
+                            // vector of TypedValues
+                            utils::FnvCollection<utils::pmr::vector<TypedValue>,
+                                                 TypedValue, TypedValue::Hash>,
+                            // custom equality
+                            TypedValueVectorEqual>
       aggregation_;
   // iterator over the accumulated cache
   decltype(aggregation_.begin()) aggregation_it_ = aggregation_.begin();
@@ -2513,7 +2496,7 @@ class AggregateCursor : public Cursor {
    */
   void ProcessOne(const Frame &frame, ExpressionEvaluator *evaluator) {
     auto *mem = aggregation_.get_allocator().GetMemoryResource();
-    std::vector<TypedValue, utils::Allocator<TypedValue>> group_by(mem);
+    utils::pmr::vector<TypedValue> group_by(mem);
     group_by.reserve(self_.group_by_.size());
     for (Expression *expression : self_.group_by_) {
       group_by.emplace_back(expression->Accept(*evaluator));
@@ -2851,14 +2834,14 @@ class OrderByCursor : public Cursor {
       auto *mem = cache_.get_allocator().GetMemoryResource();
       while (input_cursor_->Pull(frame, context)) {
         // collect the order_by elements
-        std::vector<TypedValue, utils::Allocator<TypedValue>> order_by(mem);
+        utils::pmr::vector<TypedValue> order_by(mem);
         order_by.reserve(self_.order_by_.size());
         for (auto expression_ptr : self_.order_by_) {
           order_by.emplace_back(expression_ptr->Accept(evaluator));
         }
 
         // collect the output elements
-        std::vector<TypedValue, utils::Allocator<TypedValue>> output(mem);
+        utils::pmr::vector<TypedValue> output(mem);
         output.reserve(self_.output_symbols_.size());
         for (const Symbol &output_sym : self_.output_symbols_)
           output.emplace_back(frame[output_sym]);
@@ -2901,8 +2884,8 @@ class OrderByCursor : public Cursor {
 
  private:
   struct Element {
-    std::vector<TypedValue, utils::Allocator<TypedValue>> order_by;
-    std::vector<TypedValue, utils::Allocator<TypedValue>> remember;
+    utils::pmr::vector<TypedValue> order_by;
+    utils::pmr::vector<TypedValue> remember;
   };
 
   const OrderBy &self_;
@@ -2910,7 +2893,7 @@ class OrderByCursor : public Cursor {
   bool did_pull_all_{false};
   // a cache of elements pulled from the input
   // the cache is filled and sorted (only on first elem) on first Pull
-  std::vector<Element, utils::Allocator<Element>> cache_;
+  utils::pmr::vector<Element> cache_;
   // iterator over the cache_, maintains state between Pulls
   decltype(cache_.begin()) cache_it_ = cache_.begin();
 };
@@ -3150,7 +3133,7 @@ class UnwindCursor : public Cursor {
   const Unwind &self_;
   const UniqueCursorPtr input_cursor_;
   // typed values we are unwinding and yielding
-  std::vector<TypedValue, utils::Allocator<TypedValue>> input_value_;
+  utils::pmr::vector<TypedValue> input_value_;
   // current position in input_value_
   decltype(input_value_)::iterator input_value_it_ = input_value_.end();
 };
@@ -3172,7 +3155,7 @@ class DistinctCursor : public Cursor {
     while (true) {
       if (!input_cursor_->Pull(frame, context)) return false;
 
-      std::vector<TypedValue, utils::Allocator<TypedValue>> row(
+      utils::pmr::vector<TypedValue> row(
           seen_rows_.get_allocator().GetMemoryResource());
       row.reserve(self_.value_symbols_.size());
       for (const auto &symbol : self_.value_symbols_)
@@ -3192,14 +3175,12 @@ class DistinctCursor : public Cursor {
   const Distinct &self_;
   const UniqueCursorPtr input_cursor_;
   // a set of already seen rows
-  std::unordered_set<
-      std::vector<TypedValue, utils::Allocator<TypedValue>>,
-      // use FNV collection hashing specialized for a vector of TypedValue
-      utils::FnvCollection<
-          std::vector<TypedValue, utils::Allocator<TypedValue>>, TypedValue,
-          TypedValue::Hash>,
-      TypedValueVectorEqual,
-      utils::Allocator<std::vector<TypedValue, utils::Allocator<TypedValue>>>>
+  utils::pmr::unordered_set<utils::pmr::vector<TypedValue>,
+                            // use FNV collection hashing specialized for a
+                            // vector of TypedValue
+                            utils::FnvCollection<utils::pmr::vector<TypedValue>,
+                                                 TypedValue, TypedValue::Hash>,
+                            TypedValueVectorEqual>
       seen_rows_;
 };
 
@@ -3266,10 +3247,8 @@ Union::UnionCursor::UnionCursor(const Union &self, utils::MemoryResource *mem)
 bool Union::UnionCursor::Pull(Frame &frame, ExecutionContext &context) {
   SCOPED_PROFILE_OP("Union");
 
-  std::unordered_map<std::string, TypedValue, std::hash<std::string>,
-                     std::equal_to<>,
-                     utils::Allocator<std::pair<const std::string, TypedValue>>>
-      results(context.evaluation_context.memory);
+  utils::pmr::unordered_map<std::string, TypedValue> results(
+      context.evaluation_context.memory);
   if (left_cursor_->Pull(frame, context)) {
     // collect values from the left child
     for (const auto &output_symbol : self_.left_symbols_) {
@@ -3395,11 +3374,12 @@ class CartesianCursor : public Cursor {
 
  private:
   const Cartesian &self_;
-  utils::AVector<utils::AVector<TypedValue>> left_op_frames_;
-  utils::AVector<TypedValue> right_op_frame_;
+  utils::pmr::vector<utils::pmr::vector<TypedValue>> left_op_frames_;
+  utils::pmr::vector<TypedValue> right_op_frame_;
   const UniqueCursorPtr left_op_cursor_;
   const UniqueCursorPtr right_op_cursor_;
-  utils::AVector<utils::AVector<TypedValue>>::iterator left_op_frames_it_;
+  utils::pmr::vector<utils::pmr::vector<TypedValue>>::iterator
+      left_op_frames_it_;
   bool cartesian_pull_initialized_{false};
 };
 
diff --git a/src/query/typed_value.hpp b/src/query/typed_value.hpp
index 8119fc61c..d697f03ec 100644
--- a/src/query/typed_value.hpp
+++ b/src/query/typed_value.hpp
@@ -15,6 +15,9 @@
 #include "storage/vertex_accessor.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/memory.hpp"
+#include "utils/pmr/map.hpp"
+#include "utils/pmr/string.hpp"
+#include "utils/pmr/vector.hpp"
 
 namespace query {
 
@@ -68,22 +71,15 @@ class TypedValue {
     Path
   };
 
-  /** Concrete value type of character string */
-  using TString =
-      std::basic_string<char, std::char_traits<char>, utils::Allocator<char>>;
-
   // TypedValue at this exact moment of compilation is an incomplete type, and
   // the standard says that instantiating a container with an incomplete type
   // invokes undefined behaviour. The libstdc++-8.3.0 we are using supports
   // std::map with incomplete type, but this is still murky territory. Note that
   // since C++17, std::vector is explicitly said to support incomplete types.
 
-  // Use transparent std::less<void> which forwards to `operator<`, so that it's
-  // possible to use `find` with C-style (null terminated) strings without
-  // actually constructing (and allocating) a key.
-  using TMap = std::map<TString, TypedValue, std::less<void>,
-                        utils::Allocator<std::pair<const TString, TypedValue>>>;
-  using TVector = std::vector<TypedValue, utils::Allocator<TypedValue>>;
+  using TString = utils::pmr::string;
+  using TVector = utils::pmr::vector<TypedValue>;
+  using TMap = utils::pmr::map<utils::pmr::string, TypedValue>;
 
   /** Allocator type so that STL containers are aware that we need one */
   using allocator_type = utils::Allocator<TypedValue>;
diff --git a/src/utils/memory.hpp b/src/utils/memory.hpp
index 567665fa1..1317117b0 100644
--- a/src/utils/memory.hpp
+++ b/src/utils/memory.hpp
@@ -262,9 +262,6 @@ bool operator!=(const Allocator<T> &a, const Allocator<U> &b) {
   return !(a == b);
 }
 
-template <class T>
-using AVector = std::vector<T, Allocator<T>>;
-
 /// Wraps std::pmr::memory_resource for use with out MemoryResource
 class StdMemoryResource final : public MemoryResource {
  public:
@@ -410,6 +407,9 @@ class MonotonicBufferResource final : public MemoryResource {
 
 namespace impl {
 
+template <class T>
+using AVector = std::vector<T, Allocator<T>>;
+
 /// Holds a number of Chunks each serving blocks of particular size. When a
 /// Chunk runs out of available blocks, a new Chunk is allocated. The naming is
 /// taken from `libstdc++` implementation, but the implementation details are
@@ -532,11 +532,11 @@ class PoolResource final : public MemoryResource {
   // `impl::Pool` stores a `chunks_` vector.
 
   // Pools are sorted by bound_size_, ascending.
-  AVector<impl::Pool> pools_;
+  impl::AVector<impl::Pool> pools_;
   impl::Pool *last_alloc_pool_{nullptr};
   impl::Pool *last_dealloc_pool_{nullptr};
   // Unpooled BigBlocks are sorted by data pointer.
-  AVector<BigBlock> unpooled_;
+  impl::AVector<BigBlock> unpooled_;
   size_t max_blocks_per_chunk_;
   size_t max_block_size_;
 
diff --git a/src/utils/pmr/list.hpp b/src/utils/pmr/list.hpp
new file mode 100644
index 000000000..efdd6065e
--- /dev/null
+++ b/src/utils/pmr/list.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <list>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+template <class T>
+using list = std::list<T, utils::Allocator<T>>;
+
+}  // namespace utils::pmr
diff --git a/src/utils/pmr/map.hpp b/src/utils/pmr/map.hpp
new file mode 100644
index 000000000..66d70e4a7
--- /dev/null
+++ b/src/utils/pmr/map.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <map>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+// Use transparent std::less<void> which forwards to `operator<`, so that, for
+// example, it's possible to use `find` with C-style (null terminated) strings
+// without actually constructing (and allocating) a key.
+template <class Key, class T, class Compare = std::less<void>>
+using map =
+    std::map<Key, T, Compare, utils::Allocator<std::pair<const Key, T>>>;
+
+}  // namespace utils::pmr
diff --git a/src/utils/pmr/string.hpp b/src/utils/pmr/string.hpp
new file mode 100644
index 000000000..3f782caff
--- /dev/null
+++ b/src/utils/pmr/string.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <string>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+using string =
+    std::basic_string<char, std::char_traits<char>, utils::Allocator<char>>;
+
+}  // namespace utils::pmr
diff --git a/src/utils/pmr/unordered_map.hpp b/src/utils/pmr/unordered_map.hpp
new file mode 100644
index 000000000..98f710f36
--- /dev/null
+++ b/src/utils/pmr/unordered_map.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <unordered_map>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+// Use transparent std::equal_to<void> which forwards to `operator==`, so that,
+// for example, it's possible to use `find` with C-style (null terminated)
+// strings without actually constructing (and allocating) a key.
+template <class Key, class T, class Hash = std::hash<Key>,
+          class Pred = std::equal_to<void>>
+using unordered_map =
+    std::unordered_map<Key, T, Hash, Pred,
+                       utils::Allocator<std::pair<const Key, T>>>;
+
+}  // namespace utils::pmr
diff --git a/src/utils/pmr/unordered_set.hpp b/src/utils/pmr/unordered_set.hpp
new file mode 100644
index 000000000..71af94ac5
--- /dev/null
+++ b/src/utils/pmr/unordered_set.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <unordered_set>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+// Use transparent std::equal_to<void> which forwards to `operator==`, so that,
+// for example, it's possible to use `find` with C-style (null terminated)
+// strings without actually constructing (and allocating) a key.
+template <class Key, class Hash = std::hash<Key>,
+          class Pred = std::equal_to<void>>
+using unordered_set =
+    std::unordered_set<Key, Hash, Pred, utils::Allocator<Key>>;
+
+}  // namespace utils::pmr
diff --git a/src/utils/pmr/vector.hpp b/src/utils/pmr/vector.hpp
new file mode 100644
index 000000000..5949ccfed
--- /dev/null
+++ b/src/utils/pmr/vector.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <vector>
+
+#include "utils/memory.hpp"
+
+namespace utils::pmr {
+
+template <class T>
+using vector = std::vector<T, utils::Allocator<T>>;
+
+}  // namespace utils::pmr
diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp
index 5d82c751e..2ecde3f08 100644
--- a/tests/unit/query_plan_match_filter_return.cpp
+++ b/tests/unit/query_plan_match_filter_return.cpp
@@ -583,7 +583,7 @@ class QueryPlanExpandVariable : public testing::Test {
     Frame frame(symbol_table.max_position());
     auto cursor = input_op->MakeCursor(utils::NewDeleteResource());
     auto context = MakeContext(storage, symbol_table, &dba_);
-    std::vector<utils::AVector<TypedValue>> results;
+    std::vector<utils::pmr::vector<TypedValue>> results;
     while (cursor->Pull(frame, context))
       results.emplace_back(frame[symbol].ValueList());
     return results;