diff --git a/Cargo.lock b/Cargo.lock
index f6b9a92593..69960011b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1639,6 +1639,15 @@ version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
 
+[[package]]
+name = "ecow"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54bfbb1708988623190a6c4dbedaeaf0f53c20c6395abd6a01feb327b3146f4b"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "ego-tree"
 version = "0.10.0"
@@ -3960,6 +3969,7 @@ dependencies = [
  "chrono-humanize",
  "dirs",
  "dirs-sys",
+ "ecow",
  "fancy-regex",
  "heck",
  "indexmap",
diff --git a/crates/nu-cli/src/commands/history/history_import.rs b/crates/nu-cli/src/commands/history/history_import.rs
index 80237acb87..0b2c555fed 100644
--- a/crates/nu-cli/src/commands/history/history_import.rs
+++ b/crates/nu-cli/src/commands/history/history_import.rs
@@ -170,7 +170,7 @@ fn error_from_reedline(e: ReedlineError) -> ShellError {
 fn item_from_value(v: Value) -> Result<HistoryItem, ShellError> {
     let span = v.span();
     match v {
-        Value::Record { val, .. } => item_from_record(val.into_owned(), span),
+        Value::Record { val, .. } => item_from_record(val, span),
         Value::String { val, .. } => Ok(HistoryItem {
             command_line: val,
             id: None,
diff --git a/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs b/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs
index 77c668167a..446200e0b8 100644
--- a/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs
+++ b/crates/nu-cmd-extra/src/extra/filters/roll/mod.rs
@@ -58,7 +58,7 @@ fn horizontal_rotate_value(
         Value::Record { val: record, .. } => {
             let rotations = by.map(|n| n % record.len()).unwrap_or(1);
 
-            let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
+            let (mut cols, mut vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
             if !cells_only {
                 match direction {
                     HorizontalDirection::Right => cols.rotate_right(rotations),
diff --git a/crates/nu-cmd-extra/src/extra/filters/rotate.rs b/crates/nu-cmd-extra/src/extra/filters/rotate.rs
index 43c83d42b5..b09684fa90 100644
--- a/crates/nu-cmd-extra/src/extra/filters/rotate.rs
+++ b/crates/nu-cmd-extra/src/extra/filters/rotate.rs
@@ -174,7 +174,7 @@ pub fn rotate(
             let span = val.span();
             match val {
                 Value::Record { val: record, .. } => {
-                    let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
+                    let (cols, vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
                     old_column_names = cols;
                     new_values.extend_from_slice(&vals);
                 }
diff --git a/crates/nu-cmd-extra/src/extra/filters/update_cells.rs b/crates/nu-cmd-extra/src/extra/filters/update_cells.rs
index a3edf7754a..f9462bd90a 100644
--- a/crates/nu-cmd-extra/src/extra/filters/update_cells.rs
+++ b/crates/nu-cmd-extra/src/extra/filters/update_cells.rs
@@ -127,7 +127,6 @@ impl Iterator for UpdateCellIterator {
         let mut value = self.iter.next()?;
 
         let value = if let Value::Record { val, .. } = &mut value {
-            let val = val.to_mut();
             if let Some(columns) = &self.columns {
                 for (col, val) in val.iter_mut() {
                     if columns.contains(col) {
diff --git a/crates/nu-cmd-lang/src/core_commands/describe.rs b/crates/nu-cmd-lang/src/core_commands/describe.rs
index b3f7b50611..b498cb86ce 100644
--- a/crates/nu-cmd-lang/src/core_commands/describe.rs
+++ b/crates/nu-cmd-lang/src/core_commands/describe.rs
@@ -266,16 +266,15 @@ fn describe_value_inner(
         | Value::String { .. }
         | Value::Glob { .. }
         | Value::Nothing { .. } => Description::String(value.get_type().to_string()),
-        Value::Record { val, .. } => {
-            let mut columns = val.into_owned();
-            for (_, val) in &mut columns {
+        Value::Record { mut val, .. } => {
+            for (_, val) in &mut val {
                 *val =
                     describe_value_inner(std::mem::take(val), head, engine_state).into_value(head);
             }
 
             Description::Record(record! {
                 "type" => Value::string("record", head),
-                "columns" => Value::record(columns, head),
+                "columns" => Value::record(val, head),
             })
         }
         Value::List { mut vals, .. } => {
diff --git a/crates/nu-cmd-lang/src/example_support.rs b/crates/nu-cmd-lang/src/example_support.rs
index b3a64dc168..f72ee5fb52 100644
--- a/crates/nu-cmd-lang/src/example_support.rs
+++ b/crates/nu-cmd-lang/src/example_support.rs
@@ -289,7 +289,7 @@ impl std::fmt::Debug for DebuggableValue<'_> {
             Value::Record { val, .. } => {
                 write!(f, "{{")?;
                 let mut first = true;
-                for (col, value) in (&**val).into_iter() {
+                for (col, value) in val {
                     if !first {
                         write!(f, ", ")?;
                     }
diff --git a/crates/nu-command/src/conversions/into/record.rs b/crates/nu-command/src/conversions/into/record.rs
index bba7dc9d7c..7c6471d1b8 100644
--- a/crates/nu-command/src/conversions/into/record.rs
+++ b/crates/nu-command/src/conversions/into/record.rs
@@ -134,7 +134,7 @@ fn into_record(call: &Call, input: PipelineData) -> Result<PipelineData, ShellEr
                         if matches!(expected_type, None | Some(ExpectedType::Record)) =>
                     {
                         // Don't use .extend() unless that gets changed to check for duplicate keys
-                        for (key, val) in val.into_owned() {
+                        for (key, val) in val {
                             record.insert(key, val);
                         }
                         expected_type = Some(ExpectedType::Record);
diff --git a/crates/nu-command/src/conversions/into/value.rs b/crates/nu-command/src/conversions/into/value.rs
index eb2cf3a278..96a5541526 100644
--- a/crates/nu-command/src/conversions/into/value.rs
+++ b/crates/nu-command/src/conversions/into/value.rs
@@ -110,8 +110,7 @@ impl Iterator for UpdateCellIterator {
                 let span = val.span();
                 match val {
                     Value::Record { val, .. } => Some(Value::record(
-                        val.into_owned()
-                            .into_iter()
+                        val.into_iter()
                             .map(|(col, val)| match &self.columns {
                                 Some(cols) if !cols.contains(&col) => (col, val),
                                 _ => (
diff --git a/crates/nu-command/src/database/values/sqlite.rs b/crates/nu-command/src/database/values/sqlite.rs
index 8959cf5998..598f02eeb6 100644
--- a/crates/nu-command/src/database/values/sqlite.rs
+++ b/crates/nu-command/src/database/values/sqlite.rs
@@ -465,7 +465,7 @@ pub fn nu_value_to_params(value: Value) -> Result<NuSqlParams, ShellError> {
         Value::Record { val, .. } => {
             let mut params = Vec::with_capacity(val.len());
 
-            for (mut column, value) in val.into_owned().into_iter() {
+            for (mut column, value) in val {
                 let sql_type_erased = value_to_sql(value)?;
 
                 if !column.starts_with([':', '@', '$']) {
diff --git a/crates/nu-command/src/debug/inspect_table.rs b/crates/nu-command/src/debug/inspect_table.rs
index 6bd5a3cce8..d9cdb952c6 100644
--- a/crates/nu-command/src/debug/inspect_table.rs
+++ b/crates/nu-command/src/debug/inspect_table.rs
@@ -210,7 +210,7 @@ mod util {
         let span = value.span();
         match value {
             Value::Record { val: record, .. } => {
-                let (cols, vals): (Vec<_>, Vec<_>) = record.into_owned().into_iter().unzip();
+                let (cols, vals): (Vec<_>, Vec<_>) = record.into_iter().unzip();
                 (
                     match cols.is_empty() {
                         true => vec![String::from("")],
diff --git a/crates/nu-command/src/env/load_env.rs b/crates/nu-command/src/env/load_env.rs
index b508aa6f3b..d1bad3fa11 100644
--- a/crates/nu-command/src/env/load_env.rs
+++ b/crates/nu-command/src/env/load_env.rs
@@ -43,7 +43,7 @@ impl Command for LoadEnv {
         let record = match arg {
             Some(record) => record,
             None => match input {
-                PipelineData::Value(Value::Record { val, .. }, ..) => val.into_owned(),
+                PipelineData::Value(Value::Record { val, .. }, ..) => val,
                 _ => {
                     return Err(ShellError::UnsupportedInput {
                         msg: "'load-env' expects a single record".into(),
diff --git a/crates/nu-command/src/filters/columns.rs b/crates/nu-command/src/filters/columns.rs
index e0d5b273a8..a288968e8e 100644
--- a/crates/nu-command/src/filters/columns.rs
+++ b/crates/nu-command/src/filters/columns.rs
@@ -94,7 +94,6 @@ fn getcol(head: Span, input: PipelineData) -> Result<PipelineData, ShellError> {
                         .collect()
                 }
                 Value::Record { val, .. } => val
-                    .into_owned()
                     .into_iter()
                     .map(move |(x, _)| Value::string(x, head))
                     .collect(),
diff --git a/crates/nu-command/src/filters/default.rs b/crates/nu-command/src/filters/default.rs
index c9a1506d4b..d6f8490d18 100644
--- a/crates/nu-command/src/filters/default.rs
+++ b/crates/nu-command/src/filters/default.rs
@@ -123,7 +123,6 @@ fn default(
                         val: ref mut record,
                         ..
                     } => {
-                        let record = record.to_mut();
                         if let Some(val) = record.get_mut(&column.item) {
                             if matches!(val, Value::Nothing { .. })
                                 || (default_when_empty && val.is_empty())
diff --git a/crates/nu-command/src/filters/drop/column.rs b/crates/nu-command/src/filters/drop/column.rs
index b69a15b2d7..7d083d180f 100644
--- a/crates/nu-command/src/filters/drop/column.rs
+++ b/crates/nu-command/src/filters/drop/column.rs
@@ -128,7 +128,7 @@ fn drop_cols(
                     ..
                 } => {
                     let len = record.len().saturating_sub(columns);
-                    record.to_mut().truncate(len);
+                    record.truncate(len);
                     Ok(v.into_pipeline_data_with_metadata(metadata))
                 }
                 // Propagate errors
@@ -149,7 +149,9 @@ fn drop_cols(
 fn drop_cols_set(val: &mut Value, head: Span, drop: usize) -> Result<HashSet<String>, ShellError> {
     if let Value::Record { val: record, .. } = val {
         let len = record.len().saturating_sub(drop);
-        Ok(record.to_mut().drain(len..).map(|(col, _)| col).collect())
+        let set = record.columns().skip(len).cloned().collect();
+        record.truncate(len);
+        Ok(set)
     } else {
         Err(unsupported_value_error(val, head))
     }
@@ -161,7 +163,7 @@ fn drop_record_cols(
     drop_cols: &HashSet<String>,
 ) -> Result<(), ShellError> {
     if let Value::Record { val, .. } = val {
-        val.to_mut().retain(|col, _| !drop_cols.contains(col));
+        val.retain(|col, _| !drop_cols.contains(col));
         Ok(())
     } else {
         Err(unsupported_value_error(val, head))
diff --git a/crates/nu-command/src/filters/flatten.rs b/crates/nu-command/src/filters/flatten.rs
index 982db17029..014febf723 100644
--- a/crates/nu-command/src/filters/flatten.rs
+++ b/crates/nu-command/src/filters/flatten.rs
@@ -156,7 +156,7 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec<Value> {
             let mut out = IndexMap::<String, Value>::new();
             let mut inner_table = None;
 
-            for (column_index, (column, value)) in val.into_owned().into_iter().enumerate() {
+            for (column_index, (column, value)) in val.into_iter().enumerate() {
                 let column_requested = columns.iter().find(|c| c.to_column_name() == column);
                 let need_flatten = { columns.is_empty() || column_requested.is_some() };
                 let span = value.span();
@@ -164,7 +164,7 @@ fn flat_value(columns: &[CellPath], item: Value, all: bool) -> Vec<Value> {
                 match value {
                     Value::Record { ref val, .. } => {
                         if need_flatten {
-                            for (col, val) in val.clone().into_owned() {
+                            for (col, val) in val.clone() {
                                 if out.contains_key(&col) {
                                     out.insert(format!("{column}_{col}"), val);
                                 } else {
diff --git a/crates/nu-command/src/filters/headers.rs b/crates/nu-command/src/filters/headers.rs
index 6798b3142a..3599749685 100644
--- a/crates/nu-command/src/filters/headers.rs
+++ b/crates/nu-command/src/filters/headers.rs
@@ -142,7 +142,6 @@ fn replace_headers(
             if let Value::Record { val: record, .. } = value {
                 Ok(Value::record(
                     record
-                        .into_owned()
                         .into_iter()
                         .filter_map(|(col, val)| {
                             old_headers
diff --git a/crates/nu-command/src/filters/items.rs b/crates/nu-command/src/filters/items.rs
index a32f2808b8..85b8c7312f 100644
--- a/crates/nu-command/src/filters/items.rs
+++ b/crates/nu-command/src/filters/items.rs
@@ -49,7 +49,6 @@ impl Command for Items {
                     Value::Record { val, .. } => {
                         let mut closure = ClosureEval::new(engine_state, stack, closure);
                         Ok(val
-                            .into_owned()
                             .into_iter()
                             .map_while(move |(col, val)| {
                                 let result = closure
diff --git a/crates/nu-command/src/filters/merge/common.rs b/crates/nu-command/src/filters/merge/common.rs
index 849e649d56..70fa378f31 100644
--- a/crates/nu-command/src/filters/merge/common.rs
+++ b/crates/nu-command/src/filters/merge/common.rs
@@ -66,7 +66,7 @@ pub(crate) fn do_merge(
             Value::Record { val: lhs, .. },
             Value::Record { val: rhs, .. },
         ) => Ok(Value::record(
-            merge_records(lhs.into_owned(), rhs.into_owned(), strategy, span)?,
+            merge_records(lhs, rhs, strategy, span)?,
             span,
         )),
         // Deep merge records
@@ -75,7 +75,7 @@ pub(crate) fn do_merge(
             Value::Record { val: lhs, .. },
             Value::Record { val: rhs, .. },
         ) => Ok(Value::record(
-            merge_records(lhs.into_owned(), rhs.into_owned(), strategy, span)?,
+            merge_records(lhs, rhs, strategy, span)?,
             span,
         )),
         // Merge lists by appending
diff --git a/crates/nu-command/src/filters/rename.rs b/crates/nu-command/src/filters/rename.rs
index 174d8d43ae..ac4d607ad6 100644
--- a/crates/nu-command/src/filters/rename.rs
+++ b/crates/nu-command/src/filters/rename.rs
@@ -148,8 +148,7 @@ fn rename(
                     Value::Record { val: record, .. } => {
                         let record =
                             if let Some(closure) = &mut closure {
-                                record
-                                    .into_owned().into_iter()
+                                record.into_iter()
                                     .map(|(col, val)| {
                                         let col = Value::string(col, span);
                                         let data = closure.run_with_value(col)?;
@@ -163,7 +162,7 @@ fn rename(
                                         // record columns are unique so we can track the number
                                         // of renamed columns to check if any were missed
                                         let mut renamed = 0;
-                                        let record = record.into_owned().into_iter().map(|(col, val)| {
+                                        let record = record.into_iter().map(|(col, val)| {
                                             let col = if let Some(col) = columns.get(&col) {
                                                 renamed += 1;
                                                 col.clone()
@@ -194,7 +193,7 @@ fn rename(
                                         }
                                     }
                                     None => Ok(record
-                                        .into_owned().into_iter()
+                                        .into_iter()
                                         .enumerate()
                                         .map(|(i, (col, val))| {
                                             (columns.get(i).cloned().unwrap_or(col), val)
diff --git a/crates/nu-command/src/filters/sort.rs b/crates/nu-command/src/filters/sort.rs
index 7eb37d5837..3d9200f4e0 100644
--- a/crates/nu-command/src/filters/sort.rs
+++ b/crates/nu-command/src/filters/sort.rs
@@ -146,13 +146,7 @@ impl Command for Sort {
         let sorted: Value = match value {
             Value::Record { val, .. } => {
                 // Records have two sorting methods, toggled by presence or absence of -v
-                let record = crate::sort_record(
-                    val.into_owned(),
-                    sort_by_value,
-                    reverse,
-                    insensitive,
-                    natural,
-                )?;
+                let record = crate::sort_record(val, sort_by_value, reverse, insensitive, natural)?;
                 Value::record(record, span)
             }
             value @ Value::List { .. } => {
diff --git a/crates/nu-command/src/filters/uniq.rs b/crates/nu-command/src/filters/uniq.rs
index 8042963d75..2220703c1f 100644
--- a/crates/nu-command/src/filters/uniq.rs
+++ b/crates/nu-command/src/filters/uniq.rs
@@ -194,7 +194,6 @@ fn sort_attributes(val: Value) -> Value {
         Value::Record { val, .. } => {
             // TODO: sort inplace
             let sorted = val
-                .into_owned()
                 .into_iter()
                 .sorted_by(|a, b| a.0.cmp(&b.0))
                 .collect_vec();
diff --git a/crates/nu-command/src/filters/values.rs b/crates/nu-command/src/filters/values.rs
index 5039938055..2fb415fc34 100644
--- a/crates/nu-command/src/filters/values.rs
+++ b/crates/nu-command/src/filters/values.rs
@@ -106,7 +106,7 @@ pub fn get_values<'a>(
     for item in input {
         match item {
             Value::Record { val, .. } => {
-                for (k, v) in &**val {
+                for (k, v) in val {
                     if let Some(vec) = output.get_mut(k) {
                         vec.push(v.clone());
                     } else {
diff --git a/crates/nu-command/src/formats/to/json.rs b/crates/nu-command/src/formats/to/json.rs
index 55d5d80b7a..cf1c6ebd01 100644
--- a/crates/nu-command/src/formats/to/json.rs
+++ b/crates/nu-command/src/formats/to/json.rs
@@ -161,7 +161,7 @@ pub fn value_to_json_value(
         }
         Value::Record { val, .. } => {
             let mut m = nu_json::Map::new();
-            for (k, v) in &**val {
+            for (k, v) in val {
                 m.insert(
                     k.clone(),
                     value_to_json_value(engine_state, v, call_span, serialize_types)?,
diff --git a/crates/nu-command/src/formats/to/text.rs b/crates/nu-command/src/formats/to/text.rs
index 858c5fce29..b178d5702a 100644
--- a/crates/nu-command/src/formats/to/text.rs
+++ b/crates/nu-command/src/formats/to/text.rs
@@ -178,7 +178,6 @@ fn local_into_string(
             .collect::<Vec<_>>()
             .join(separator),
         Value::Record { val, .. } => val
-            .into_owned()
             .into_iter()
             .map(|(x, y)| {
                 format!(
diff --git a/crates/nu-command/src/formats/to/toml.rs b/crates/nu-command/src/formats/to/toml.rs
index 11630e4522..84c2a01371 100644
--- a/crates/nu-command/src/formats/to/toml.rs
+++ b/crates/nu-command/src/formats/to/toml.rs
@@ -65,7 +65,7 @@ fn helper(
         Value::String { val, .. } | Value::Glob { val, .. } => toml::Value::String(val.clone()),
         Value::Record { val, .. } => {
             let mut m = toml::map::Map::new();
-            for (k, v) in &**val {
+            for (k, v) in val {
                 m.insert(k.clone(), helper(engine_state, v, serialize_types)?);
             }
             toml::Value::Table(m)
diff --git a/crates/nu-command/src/formats/to/xml.rs b/crates/nu-command/src/formats/to/xml.rs
index 4476f654c2..1c87f52ab5 100644
--- a/crates/nu-command/src/formats/to/xml.rs
+++ b/crates/nu-command/src/formats/to/xml.rs
@@ -329,7 +329,7 @@ impl Job {
             // alternatives like {tag: a attributes: {} content: []}, {tag: a attribbutes: null
             // content: null}, {tag: a}. See to_xml_entry for more
             let attrs = match attrs {
-                Value::Record { val, .. } => val.into_owned(),
+                Value::Record { val, .. } => val,
                 Value::Nothing { .. } => Record::new(),
                 _ => {
                     return Err(ShellError::CantConvert {
diff --git a/crates/nu-command/src/formats/to/yaml.rs b/crates/nu-command/src/formats/to/yaml.rs
index 7b6f99bb67..f2697c943d 100644
--- a/crates/nu-command/src/formats/to/yaml.rs
+++ b/crates/nu-command/src/formats/to/yaml.rs
@@ -113,7 +113,7 @@ pub fn value_to_yaml_value(
         }
         Value::Record { val, .. } => {
             let mut m = serde_yaml::Mapping::new();
-            for (k, v) in &**val {
+            for (k, v) in val {
                 m.insert(
                     serde_yaml::Value::String(k.clone()),
                     value_to_yaml_value(engine_state, v, serialize_types)?,
diff --git a/crates/nu-command/src/generators/generate.rs b/crates/nu-command/src/generators/generate.rs
index 05a34dcbeb..f08fc2953b 100644
--- a/crates/nu-command/src/generators/generate.rs
+++ b/crates/nu-command/src/generators/generate.rs
@@ -202,12 +202,11 @@ fn parse_closure_result(
             match value {
                 // {out: ..., next: ...} -> output and continue
                 Value::Record { val, .. } => {
-                    let iter = val.into_owned().into_iter();
                     let mut out = None;
                     let mut next = None;
                     let mut err = None;
 
-                    for (k, v) in iter {
+                    for (k, v) in val {
                         if k.eq_ignore_ascii_case("out") {
                             out = Some(v);
                         } else if k.eq_ignore_ascii_case("next") {
diff --git a/crates/nu-command/src/help/help_.rs b/crates/nu-command/src/help/help_.rs
index 3cdd27a672..f21e591761 100644
--- a/crates/nu-command/src/help/help_.rs
+++ b/crates/nu-command/src/help/help_.rs
@@ -150,7 +150,7 @@ pub fn highlight_search_in_table(
             });
         };
 
-        let has_match = record.to_mut().iter_mut().try_fold(
+        let has_match = record.iter_mut().try_fold(
             false,
             |acc: bool, (col, val)| -> Result<bool, ShellError> {
                 if !searched_cols.contains(&col.as_str()) {
diff --git a/crates/nu-command/src/math/utils.rs b/crates/nu-command/src/math/utils.rs
index 9041f23ffa..9fc8708031 100644
--- a/crates/nu-command/src/math/utils.rs
+++ b/crates/nu-command/src/math/utils.rs
@@ -29,7 +29,7 @@ fn helper_for_tables(
     for val in values {
         match val {
             Value::Record { val, .. } => {
-                for (key, value) in &**val {
+                for (key, value) in val {
                     column_values
                         .entry(key.clone())
                         .and_modify(|v: &mut Vec<Value>| v.push(value.clone()))
@@ -82,15 +82,13 @@ pub fn calculate(
             ),
             _ => mf(vals, span, name),
         },
-        PipelineData::Value(Value::Record { val, .. }, ..) => {
-            let mut record = val.into_owned();
-            record
-                .iter_mut()
+        PipelineData::Value(Value::Record { mut val, .. }, ..) => {
+            val.iter_mut()
                 .try_for_each(|(_, val)| -> Result<(), ShellError> {
                     *val = mf(slice::from_ref(val), span, name)?;
                     Ok(())
                 })?;
-            Ok(Value::record(record, span))
+            Ok(Value::record(val, span))
         }
         PipelineData::Value(Value::Range { val, .. }, ..) => {
             ensure_bounded(val.as_ref(), span, name)?;
diff --git a/crates/nu-command/src/network/http/client.rs b/crates/nu-command/src/network/http/client.rs
index c4fe4f9486..54b70de4fd 100644
--- a/crates/nu-command/src/network/http/client.rs
+++ b/crates/nu-command/src/network/http/client.rs
@@ -347,7 +347,7 @@ fn send_form_request(
         Value::Record { val, .. } => {
             let mut data: Vec<(String, String)> = Vec::with_capacity(val.len());
 
-            for (col, val) in val.into_owned() {
+            for (col, val) in val {
                 data.push((col, val.coerce_into_string()?))
             }
 
@@ -380,7 +380,7 @@ fn send_multipart_request(
                 )
             };
 
-            for (col, val) in val.into_owned() {
+            for (col, val) in val {
                 if let Value::Binary { val, .. } = val {
                     let headers = [
                         "Content-Type: application/octet-stream".to_string(),
@@ -580,7 +580,7 @@ pub fn request_add_custom_headers(
 
         match &headers {
             Value::Record { val, .. } => {
-                for (k, v) in &**val {
+                for (k, v) in val {
                     custom_headers.insert(k.to_string(), v.clone());
                 }
             }
@@ -590,7 +590,7 @@ pub fn request_add_custom_headers(
                     // single row([key1 key2]; [val1 val2])
                     match &table[0] {
                         Value::Record { val, .. } => {
-                            for (k, v) in &**val {
+                            for (k, v) in val {
                                 custom_headers.insert(k.to_string(), v.clone());
                             }
                         }
diff --git a/crates/nu-command/src/network/url/join.rs b/crates/nu-command/src/network/url/join.rs
index d6a8c65648..61465161d6 100644
--- a/crates/nu-command/src/network/url/join.rs
+++ b/crates/nu-command/src/network/url/join.rs
@@ -109,7 +109,6 @@ impl Command for UrlJoin {
                 match value {
                     Value::Record { val, .. } => {
                         let url_components = val
-                            .into_owned()
                             .into_iter()
                             .try_fold(UrlComponents::new(), |url, (k, v)| {
                                 url.add_component(k, v, head, engine_state)
diff --git a/crates/nu-command/src/stor/insert.rs b/crates/nu-command/src/stor/insert.rs
index 1d0f5ae6c0..5457c3a0a9 100644
--- a/crates/nu-command/src/stor/insert.rs
+++ b/crates/nu-command/src/stor/insert.rs
@@ -138,7 +138,7 @@ fn handle(
     values
         .into_iter()
         .map(|val| match val {
-            Value::Record { val, .. } => Ok(val.into_owned()),
+            Value::Record { val, .. } => Ok(val),
             other => Err(ShellError::OnlySupportsThisInputType {
                 exp_input_type: "record".into(),
                 wrong_type: other.get_type().to_string(),
diff --git a/crates/nu-command/src/stor/update.rs b/crates/nu-command/src/stor/update.rs
index 98652bae2a..40fc193806 100644
--- a/crates/nu-command/src/stor/update.rs
+++ b/crates/nu-command/src/stor/update.rs
@@ -120,7 +120,7 @@ fn handle(
                 });
             }
             match value {
-                Value::Record { val, .. } => Ok(val.into_owned()),
+                Value::Record { val, .. } => Ok(val),
                 val => Err(ShellError::OnlySupportsThisInputType {
                     exp_input_type: "record".into(),
                     wrong_type: val.get_type().to_string(),
diff --git a/crates/nu-command/src/viewers/griddle.rs b/crates/nu-command/src/viewers/griddle.rs
index 56c1cb1132..a715523868 100644
--- a/crates/nu-command/src/viewers/griddle.rs
+++ b/crates/nu-command/src/viewers/griddle.rs
@@ -117,7 +117,7 @@ prints out the list properly."#
                 // dbg!("value::record");
                 let mut items = vec![];
 
-                for (i, (c, v)) in val.into_owned().into_iter().enumerate() {
+                for (i, (c, v)) in val.into_iter().enumerate() {
                     items.push((i, c, v.to_expanded_string(", ", config)))
                 }
 
diff --git a/crates/nu-command/src/viewers/table.rs b/crates/nu-command/src/viewers/table.rs
index 147555558e..923c24d7bd 100644
--- a/crates/nu-command/src/viewers/table.rs
+++ b/crates/nu-command/src/viewers/table.rs
@@ -450,7 +450,7 @@ fn handle_table_command(mut input: CmdInput<'_>) -> ShellResult<PipelineData> {
         }
         PipelineData::Value(Value::Record { val, .. }, ..) => {
             input.data = PipelineData::Empty;
-            handle_record(input, val.into_owned())
+            handle_record(input, val)
         }
         PipelineData::Value(Value::Error { error, .. }, ..) => {
             // Propagate this error outward, so that it goes to stderr
@@ -688,7 +688,7 @@ fn handle_row_stream(
             stream.map(move |mut value| {
                 if let Value::Record { val: record, .. } = &mut value {
                     // Only the name column gets special colors, for now
-                    if let Some(value) = record.to_mut().get_mut("name") {
+                    if let Some(value) = record.get_mut("name") {
                         let span = value.span();
                         if let Value::String { val, .. } = value {
                             if let Some(val) =
@@ -709,7 +709,7 @@ fn handle_row_stream(
         }) => {
             stream.map(|mut value| {
                 if let Value::Record { val: record, .. } = &mut value {
-                    for (rec_col, rec_val) in record.to_mut().iter_mut() {
+                    for (rec_col, rec_val) in record.iter_mut() {
                         // Every column in the HTML theme table except 'name' is colored
                         if rec_col != "name" {
                             continue;
diff --git a/crates/nu-engine/src/documentation.rs b/crates/nu-engine/src/documentation.rs
index 78c11bc4d0..e537677ee6 100644
--- a/crates/nu-engine/src/documentation.rs
+++ b/crates/nu-engine/src/documentation.rs
@@ -380,7 +380,7 @@ fn get_argument_for_color_value(
 ) -> Option<Argument> {
     match color {
         Value::Record { val, .. } => {
-            let record_exp: Vec<RecordItem> = (**val)
+            let record_exp: Vec<RecordItem> = val
                 .iter()
                 .map(|(k, v)| {
                     RecordItem::Pair(
diff --git a/crates/nu-explore/src/nu_common/value.rs b/crates/nu-explore/src/nu_common/value.rs
index 3b5751c11a..e6a38b826d 100644
--- a/crates/nu-explore/src/nu_common/value.rs
+++ b/crates/nu-explore/src/nu_common/value.rs
@@ -92,7 +92,7 @@ pub fn collect_input(value: Value) -> Result<(Vec<String>, Vec<Vec<Value>>)> {
     let span = value.span();
     match value {
         Value::Record { val: record, .. } => {
-            let (key, val): (_, Vec<Value>) = record.into_owned().into_iter().unzip();
+            let (key, val): (_, Vec<Value>) = record.into_iter().unzip();
 
             Ok((
                 key,
diff --git a/crates/nu-plugin-test-support/src/plugin_test.rs b/crates/nu-plugin-test-support/src/plugin_test.rs
index 1d66674824..8c07634127 100644
--- a/crates/nu-plugin-test-support/src/plugin_test.rs
+++ b/crates/nu-plugin-test-support/src/plugin_test.rs
@@ -335,8 +335,8 @@ impl PluginTest {
                 // reorder cols and vals to make more logically compare.
                 // more general, if two record have same col and values,
                 // the order of cols shouldn't affect the equal property.
-                let mut a_rec = a_rec.clone().into_owned();
-                let mut b_rec = b_rec.clone().into_owned();
+                let mut a_rec = a_rec.clone();
+                let mut b_rec = b_rec.clone();
                 a_rec.sort_cols();
                 b_rec.sort_cols();
 
diff --git a/crates/nu-protocol/Cargo.toml b/crates/nu-protocol/Cargo.toml
index e6f85a8558..e2ef2ad112 100644
--- a/crates/nu-protocol/Cargo.toml
+++ b/crates/nu-protocol/Cargo.toml
@@ -24,14 +24,18 @@ nu-derive-value = { path = "../nu-derive-value", version = "0.103.1" }
 
 brotli = { workspace = true, optional = true }
 bytes = { workspace = true }
-chrono = { workspace = true, features = [ "serde", "std", "unstable-locales" ], default-features = false }
+chrono = { workspace = true, features = [
+  "serde",
+  "std",
+  "unstable-locales",
+], default-features = false }
 chrono-humanize = { workspace = true }
 dirs = { workspace = true }
 fancy-regex = { workspace = true }
 heck = { workspace = true }
 indexmap = { workspace = true }
 lru = { workspace = true }
-miette = { workspace = true, features = ["fancy-no-backtrace"]}
+miette = { workspace = true, features = ["fancy-no-backtrace"] }
 num-format = { workspace = true }
 rmp-serde = { workspace = true, optional = true }
 serde = { workspace = true }
@@ -40,6 +44,7 @@ strum = { workspace = true }
 strum_macros = { workspace = true }
 thiserror = "2.0"
 typetag = "0.2"
+ecow = { version = "0.2.2", features = ["serde"] }
 os_pipe = { workspace = true, optional = true, features = ["io_safety"] }
 log = { workspace = true }
 web-time = { workspace = true }
@@ -54,16 +59,9 @@ windows-sys = { workspace = true }
 
 [features]
 default = ["os"]
-os = [
-  "nu-utils/os",
-  "os_pipe",
-]
+os = ["nu-utils/os", "os_pipe"]
 
-plugin = [
-  "brotli",
-  "os",
-  "rmp-serde",
-]
+plugin = ["brotli", "os", "rmp-serde"]
 
 [dev-dependencies]
 serde_json = { workspace = true }
diff --git a/crates/nu-protocol/src/engine/pattern_match.rs b/crates/nu-protocol/src/engine/pattern_match.rs
index bac2fd8d17..75c43df497 100644
--- a/crates/nu-protocol/src/engine/pattern_match.rs
+++ b/crates/nu-protocol/src/engine/pattern_match.rs
@@ -23,7 +23,7 @@ impl Matcher for Pattern {
             Pattern::Record(field_patterns) => match value {
                 Value::Record { val, .. } => {
                     'top: for field_pattern in field_patterns {
-                        for (col, val) in &**val {
+                        for (col, val) in val {
                             if col == &field_pattern.0 {
                                 // We have found the field
                                 let result = field_pattern.1.match_value(val, matches);
diff --git a/crates/nu-protocol/src/eval_base.rs b/crates/nu-protocol/src/eval_base.rs
index 15fc5105d3..c9e06f3740 100644
--- a/crates/nu-protocol/src/eval_base.rs
+++ b/crates/nu-protocol/src/eval_base.rs
@@ -87,7 +87,7 @@ pub trait Eval {
                             let inner_span = inner.span(&state);
                             match Self::eval::<D>(state, mut_state, inner)? {
                                 Value::Record { val: inner_val, .. } => {
-                                    for (col_name, val) in inner_val.into_owned() {
+                                    for (col_name, val) in inner_val {
                                         if let Some(orig_span) = col_names.get(&col_name) {
                                             return Err(ShellError::ColumnDefinedTwice {
                                                 col_name,
diff --git a/crates/nu-protocol/src/value/from_value.rs b/crates/nu-protocol/src/value/from_value.rs
index f617270d1d..a0c1f0d930 100644
--- a/crates/nu-protocol/src/value/from_value.rs
+++ b/crates/nu-protocol/src/value/from_value.rs
@@ -698,7 +698,7 @@ impl FromValue for Range {
 impl FromValue for Record {
     fn from_value(v: Value) -> Result<Self, ShellError> {
         match v {
-            Value::Record { val, .. } => Ok(val.into_owned()),
+            Value::Record { val, .. } => Ok(val),
             v => Err(ShellError::CantConvert {
                 to_type: Self::expected_type().to_string(),
                 from_type: v.get_type().to_string(),
diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs
index 2d820b044a..8762c50ea4 100644
--- a/crates/nu-protocol/src/value/mod.rs
+++ b/crates/nu-protocol/src/value/mod.rs
@@ -31,7 +31,7 @@ use fancy_regex::Regex;
 use nu_utils::{
     contains_emoji,
     locale::{get_system_locale_string, LOCALE_OVERRIDE_ENV_VAR},
-    IgnoreCaseExt, SharedCow,
+    IgnoreCaseExt,
 };
 use serde::{Deserialize, Serialize};
 use std::{
@@ -112,7 +112,7 @@ pub enum Value {
         internal_span: Span,
     },
     Record {
-        val: SharedCow<Record>,
+        val: Record,
         /// note: spans are being refactored out of Value
         /// please use .span() instead of matching this span value
         #[serde(rename = "span")]
@@ -246,6 +246,11 @@ impl Clone for Value {
     }
 }
 
+// This is to document/enforce the size of `Value` in bytes.
+// We should try to avoid increasing the size of `Value`,
+// and PRs that do so will have to change the number below so that it's noted in review.
+const _: () = assert!(std::mem::size_of::<Value>() <= 48);
+
 impl Value {
     fn cant_convert_to<T>(&self, typ: &str) -> Result<T, ShellError> {
         Err(ShellError::CantConvert {
@@ -542,7 +547,7 @@ impl Value {
     /// Unwraps the inner [`Record`] value or returns an error if this `Value` is not a record
     pub fn into_record(self) -> Result<Record, ShellError> {
         if let Value::Record { val, .. } = self {
-            Ok(val.into_owned())
+            Ok(val)
         } else {
             self.cant_convert_to("record")
         }
@@ -1185,7 +1190,7 @@ impl Value {
                     match current {
                         Value::Record { mut val, .. } => {
                             // Make reverse iterate to avoid duplicate column leads to first value, actually last value is expected.
-                            if let Some(found) = val.to_mut().iter_mut().rev().find(|x| {
+                            if let Some(found) = val.iter_mut().rev().find(|x| {
                                 if insensitive {
                                     x.0.eq_ignore_case(column_name)
                                 } else {
@@ -1220,15 +1225,13 @@ impl Value {
                                     let val_span = val.span();
                                     match val {
                                         Value::Record { mut val, .. } => {
-                                            if let Some(found) =
-                                                val.to_mut().iter_mut().rev().find(|x| {
-                                                    if insensitive {
-                                                        x.0.eq_ignore_case(column_name)
-                                                    } else {
-                                                        x.0 == column_name
-                                                    }
-                                                })
-                                            {
+                                            if let Some(found) = val.iter_mut().rev().find(|x| {
+                                                if insensitive {
+                                                    x.0.eq_ignore_case(column_name)
+                                                } else {
+                                                    x.0 == column_name
+                                                }
+                                            }) {
                                                 Ok(std::mem::take(found.1))
                                             } else if *optional {
                                                 Ok(Value::nothing(*origin_span))
@@ -1334,7 +1337,6 @@ impl Value {
                         for val in vals.iter_mut() {
                             match val {
                                 Value::Record { val: record, .. } => {
-                                    let record = record.to_mut();
                                     if let Some(val) = record.get_mut(col_name) {
                                         val.upsert_data_at_cell_path(path, new_val.clone())?;
                                     } else {
@@ -1355,7 +1357,6 @@ impl Value {
                         }
                     }
                     Value::Record { val: record, .. } => {
-                        let record = record.to_mut();
                         if let Some(val) = record.get_mut(col_name) {
                             val.upsert_data_at_cell_path(path, new_val)?;
                         } else {
@@ -1437,7 +1438,7 @@ impl Value {
                             let v_span = val.span();
                             match val {
                                 Value::Record { val: record, .. } => {
-                                    if let Some(val) = record.to_mut().get_mut(col_name) {
+                                    if let Some(val) = record.get_mut(col_name) {
                                         val.update_data_at_cell_path(path, new_val.clone())?;
                                     } else {
                                         return Err(ShellError::CantFindColumn {
@@ -1459,7 +1460,7 @@ impl Value {
                         }
                     }
                     Value::Record { val: record, .. } => {
-                        if let Some(val) = record.to_mut().get_mut(col_name) {
+                        if let Some(val) = record.get_mut(col_name) {
                             val.update_data_at_cell_path(path, new_val)?;
                         } else {
                             return Err(ShellError::CantFindColumn {
@@ -1524,7 +1525,7 @@ impl Value {
                                 let v_span = val.span();
                                 match val {
                                     Value::Record { val: record, .. } => {
-                                        if record.to_mut().remove(col_name).is_none() && !optional {
+                                        if record.remove(col_name).is_none() && !optional {
                                             return Err(ShellError::CantFindColumn {
                                                 col_name: col_name.clone(),
                                                 span: Some(*span),
@@ -1544,7 +1545,7 @@ impl Value {
                             Ok(())
                         }
                         Value::Record { val: record, .. } => {
-                            if record.to_mut().remove(col_name).is_none() && !optional {
+                            if record.remove(col_name).is_none() && !optional {
                                 return Err(ShellError::CantFindColumn {
                                     col_name: col_name.clone(),
                                     span: Some(*span),
@@ -1599,7 +1600,7 @@ impl Value {
                                 let v_span = val.span();
                                 match val {
                                     Value::Record { val: record, .. } => {
-                                        if let Some(val) = record.to_mut().get_mut(col_name) {
+                                        if let Some(val) = record.get_mut(col_name) {
                                             val.remove_data_at_cell_path(path)?;
                                         } else if !optional {
                                             return Err(ShellError::CantFindColumn {
@@ -1621,7 +1622,7 @@ impl Value {
                             Ok(())
                         }
                         Value::Record { val: record, .. } => {
-                            if let Some(val) = record.to_mut().get_mut(col_name) {
+                            if let Some(val) = record.get_mut(col_name) {
                                 val.remove_data_at_cell_path(path)?;
                             } else if !optional {
                                 return Err(ShellError::CantFindColumn {
@@ -1685,7 +1686,6 @@ impl Value {
                             let v_span = val.span();
                             match val {
                                 Value::Record { val: record, .. } => {
-                                    let record = record.to_mut();
                                     if let Some(val) = record.get_mut(col_name) {
                                         if path.is_empty() {
                                             return Err(ShellError::ColumnAlreadyExists {
@@ -1719,7 +1719,6 @@ impl Value {
                         }
                     }
                     Value::Record { val: record, .. } => {
-                        let record = record.to_mut();
                         if let Some(val) = record.get_mut(col_name) {
                             if path.is_empty() {
                                 return Err(ShellError::ColumnAlreadyExists {
@@ -1823,7 +1822,6 @@ impl Value {
         // Check for contained values
         match self {
             Value::Record { ref mut val, .. } => val
-                .to_mut()
                 .iter_mut()
                 .try_for_each(|(_, rec_value)| rec_value.recurse_mut(f)),
             Value::List { ref mut vals, .. } => vals
@@ -1958,7 +1956,7 @@ impl Value {
 
     pub fn record(val: Record, span: Span) -> Value {
         Value::Record {
-            val: SharedCow::new(val),
+            val,
             internal_span: span,
         }
     }
@@ -2355,8 +2353,8 @@ impl PartialOrd for Value {
                     // reorder cols and vals to make more logically compare.
                     // more general, if two record have same col and values,
                     // the order of cols shouldn't affect the equal property.
-                    let mut lhs = lhs.clone().into_owned();
-                    let mut rhs = rhs.clone().into_owned();
+                    let mut lhs = lhs.clone();
+                    let mut rhs = rhs.clone();
                     lhs.sort_cols();
                     rhs.sort_cols();
 
diff --git a/crates/nu-protocol/src/value/record.rs b/crates/nu-protocol/src/value/record.rs
index 2b667a7cf0..96d45ee71a 100644
--- a/crates/nu-protocol/src/value/record.rs
+++ b/crates/nu-protocol/src/value/record.rs
@@ -1,13 +1,12 @@
 //! Our insertion ordered map-type [`Record`]
-use std::{iter::FusedIterator, ops::RangeBounds};
-
 use crate::{ShellError, Span, Value};
-
+use ecow::EcoVec;
 use serde::{de::Visitor, ser::SerializeMap, Deserialize, Serialize};
+use std::iter::FusedIterator;
 
 #[derive(Debug, Clone, Default)]
 pub struct Record {
-    inner: Vec<(String, Value)>,
+    inner: EcoVec<(String, Value)>,
 }
 
 impl Record {
@@ -17,7 +16,7 @@ impl Record {
 
     pub fn with_capacity(capacity: usize) -> Self {
         Self {
-            inner: Vec::with_capacity(capacity),
+            inner: EcoVec::with_capacity(capacity),
         }
     }
 
@@ -100,12 +99,13 @@ impl Record {
 
     pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
         self.inner
+            .make_mut()
             .iter_mut()
             .find_map(|(k, v)| if k == col.as_ref() { Some(v) } else { None })
     }
 
     pub fn get_index(&self, idx: usize) -> Option<(&String, &Value)> {
-        self.inner.get(idx).map(|(col, val): &(_, _)| (col, val))
+        self.inner.get(idx).map(|(col, val)| (col, val))
     }
 
     /// Remove single value by key
@@ -152,7 +152,7 @@ impl Record {
     ///
     /// fn remove_foo_recursively(val: &mut Value) {
     ///     if let Value::Record {val, ..} = val {
-    ///         val.to_mut().retain_mut(keep_non_foo);
+    ///         val.retain_mut(keep_non_foo);
     ///     }
     /// }
     ///
@@ -184,7 +184,7 @@ impl Record {
     where
         F: FnMut(&str, &mut Value) -> bool,
     {
-        self.inner.retain_mut(|(col, val)| keep(col, val));
+        self.inner.retain(|(k, v)| keep(k, v));
     }
 
     /// Truncate record to the first `len` elements.
@@ -235,35 +235,35 @@ impl Record {
         }
     }
 
-    /// Obtain an iterator to remove elements in `range`
-    ///
-    /// Elements not consumed from the iterator will be dropped
-    ///
-    /// ```rust
-    /// use nu_protocol::{record, Value};
-    ///
-    /// let mut rec = record!(
-    ///     "a" => Value::test_nothing(),
-    ///     "b" => Value::test_int(42),
-    ///     "c" => Value::test_string("foo"),
-    /// );
-    /// {
-    ///     let mut drainer = rec.drain(1..);
-    ///     assert_eq!(drainer.next(), Some(("b".into(), Value::test_int(42))));
-    ///     // Dropping the `Drain`
-    /// }
-    /// let mut rec_iter = rec.into_iter();
-    /// assert_eq!(rec_iter.next(), Some(("a".into(), Value::test_nothing())));
-    /// assert_eq!(rec_iter.next(), None);
-    /// ```
-    pub fn drain<R>(&mut self, range: R) -> Drain
-    where
-        R: RangeBounds<usize> + Clone,
-    {
-        Drain {
-            iter: self.inner.drain(range),
-        }
-    }
+    // /// Obtain an iterator to remove elements in `range`
+    // ///
+    // /// Elements not consumed from the iterator will be dropped
+    // ///
+    // /// ```rust
+    // /// use nu_protocol::{record, Value};
+    // ///
+    // /// let mut rec = record!(
+    // ///     "a" => Value::test_nothing(),
+    // ///     "b" => Value::test_int(42),
+    // ///     "c" => Value::test_string("foo"),
+    // /// );
+    // /// {
+    // ///     let mut drainer = rec.drain(1..);
+    // ///     assert_eq!(drainer.next(), Some(("b".into(), Value::test_int(42))));
+    // ///     // Dropping the `Drain`
+    // /// }
+    // /// let mut rec_iter = rec.into_iter();
+    // /// assert_eq!(rec_iter.next(), Some(("a".into(), Value::test_nothing())));
+    // /// assert_eq!(rec_iter.next(), None);
+    // /// ```
+    // pub fn drain<R>(&mut self, range: R) -> Drain
+    // where
+    //     R: RangeBounds<usize> + Clone,
+    // {
+    //     Drain {
+    //         iter: self.inner.drain(range)
+    //     }
+    // }
 
     /// Sort the record by its columns.
     ///
@@ -288,7 +288,7 @@ impl Record {
     /// );
     /// ```
     pub fn sort_cols(&mut self) {
-        self.inner.sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
+        self.inner.make_mut().sort_by(|(k1, _), (k2, _)| k1.cmp(k2))
     }
 }
 
@@ -383,7 +383,7 @@ impl Extend<(String, Value)> for Record {
 }
 
 pub struct IntoIter {
-    iter: std::vec::IntoIter<(String, Value)>,
+    iter: ecow::vec::IntoIter<(String, Value)>,
 }
 
 impl Iterator for IntoIter {
@@ -503,7 +503,7 @@ impl<'a> IntoIterator for &'a mut Record {
 
     fn into_iter(self) -> Self::IntoIter {
         IterMut {
-            iter: self.inner.iter_mut(),
+            iter: self.inner.make_mut().iter_mut(),
         }
     }
 }
@@ -539,7 +539,7 @@ impl ExactSizeIterator for Columns<'_> {
 impl FusedIterator for Columns<'_> {}
 
 pub struct IntoColumns {
-    iter: std::vec::IntoIter<(String, Value)>,
+    iter: ecow::vec::IntoIter<(String, Value)>,
 }
 
 impl Iterator for IntoColumns {
@@ -599,7 +599,7 @@ impl ExactSizeIterator for Values<'_> {
 impl FusedIterator for Values<'_> {}
 
 pub struct IntoValues {
-    iter: std::vec::IntoIter<(String, Value)>,
+    iter: ecow::vec::IntoIter<(String, Value)>,
 }
 
 impl Iterator for IntoValues {
@@ -628,35 +628,39 @@ impl ExactSizeIterator for IntoValues {
 
 impl FusedIterator for IntoValues {}
 
-pub struct Drain<'a> {
-    iter: std::vec::Drain<'a, (String, Value)>,
-}
+// pub struct Drain<'a> {
+//     iter: std::slice::Iter<'a, (String, Value)>,
+// }
 
-impl Iterator for Drain<'_> {
-    type Item = (String, Value);
+// impl Iterator for Drain<'_> {
+//     type Item = (String, Value);
 
-    fn next(&mut self) -> Option<Self::Item> {
-        self.iter.next()
-    }
+//     fn next(&mut self) -> Option<Self::Item> {
+//         self.iter
+//             .next()
+//             .map(|(col, val)| (col.clone(), val.clone()))
+//     }
 
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
+//     fn size_hint(&self) -> (usize, Option<usize>) {
+//         self.iter.size_hint()
+//     }
+// }
 
-impl DoubleEndedIterator for Drain<'_> {
-    fn next_back(&mut self) -> Option<Self::Item> {
-        self.iter.next_back()
-    }
-}
+// impl DoubleEndedIterator for Drain<'_> {
+//     fn next_back(&mut self) -> Option<Self::Item> {
+//         self.iter
+//             .next_back()
+//             .map(|(col, val)| (col.clone(), val.clone()))
+//     }
+// }
 
-impl ExactSizeIterator for Drain<'_> {
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
+// impl ExactSizeIterator for Drain<'_> {
+//     fn len(&self) -> usize {
+//         self.iter.len()
+//     }
+// }
 
-impl FusedIterator for Drain<'_> {}
+// impl FusedIterator for Drain<'_> {}
 
 #[macro_export]
 macro_rules! record {
diff --git a/crates/nu-table/src/types/collapse.rs b/crates/nu-table/src/types/collapse.rs
index 4b4ebed172..c30777961e 100644
--- a/crates/nu-table/src/types/collapse.rs
+++ b/crates/nu-table/src/types/collapse.rs
@@ -1,7 +1,6 @@
 use nu_ansi_term::Style;
 use nu_color_config::StyleComputer;
 use nu_protocol::{Config, Value};
-use nu_utils::SharedCow;
 
 use crate::{
     common::{get_index_style, load_theme, nu_value_to_string_clean},
@@ -41,18 +40,14 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp
             // Take ownership of the record and reassign to &mut
             // We do this to have owned keys through `.into_iter`
             let record = std::mem::take(val);
-            *val = SharedCow::new(
-                record
-                    .into_owned()
-                    .into_iter()
-                    .map(|(mut header, mut val)| {
-                        colorize_value(&mut val, config, style_computer);
-                        header = colorize_text(&header, style.color_style).unwrap_or(header);
-
-                        (header, val)
-                    })
-                    .collect(),
-            );
+            *val = record
+                .into_iter()
+                .map(|(header, mut val)| {
+                    colorize_value(&mut val, config, style_computer);
+                    let header = colorize_text(&header, style.color_style).unwrap_or(header);
+                    (header, val)
+                })
+                .collect();
         }
         Value::List { vals, .. } => {
             for val in vals {
diff --git a/crates/nu-table/src/unstructured_table.rs b/crates/nu-table/src/unstructured_table.rs
index 1ce5f164ee..a17537a886 100644
--- a/crates/nu-table/src/unstructured_table.rs
+++ b/crates/nu-table/src/unstructured_table.rs
@@ -71,7 +71,7 @@ fn build_table(
 
 fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
     match value {
-        Value::Record { val, .. } => build_vertical_map(val.into_owned(), config),
+        Value::Record { val, .. } => build_vertical_map(val, config),
         Value::List { vals, .. } => {
             let rebuild_array_as_map = is_valid_record(&vals) && count_columns_in_record(&vals) > 0;
             if rebuild_array_as_map {
@@ -174,7 +174,7 @@ fn build_map_from_record(vals: Vec<Value>, config: &Config) -> TableValue {
 
     for val in vals {
         let val = get_as_record(val);
-        for (i, (_, val)) in val.into_owned().into_iter().enumerate() {
+        for (i, (_, val)) in val.into_iter().enumerate() {
             let value = convert_nu_value_to_table_value(val, config);
             let list = get_table_value_column_mut(&mut list[i]);
 
@@ -194,7 +194,7 @@ fn get_table_value_column_mut(val: &mut TableValue) -> &mut Vec<TableValue> {
     }
 }
 
-fn get_as_record(val: Value) -> nu_utils::SharedCow<Record> {
+fn get_as_record(val: Value) -> Record {
     match val {
         Value::Record { val, .. } => val,
         _ => unreachable!(),
diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/mod.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/mod.rs
index e4191012c7..f3d4f85a55 100644
--- a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/mod.rs
+++ b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/mod.rs
@@ -183,11 +183,9 @@ impl NuDataFrame {
 
                     conversion::insert_record(&mut column_values, record, &maybe_schema)?
                 }
-                Value::Record { val: record, .. } => conversion::insert_record(
-                    &mut column_values,
-                    record.into_owned(),
-                    &maybe_schema,
-                )?,
+                Value::Record { val: record, .. } => {
+                    conversion::insert_record(&mut column_values, record, &maybe_schema)?
+                }
                 _ => {
                     let key = "0".to_string();
                     conversion::insert_value(value, key.into(), &mut column_values, &maybe_schema)?
diff --git a/crates/nuon/src/to.rs b/crates/nuon/src/to.rs
index fae454cd9a..02c6242694 100644
--- a/crates/nuon/src/to.rs
+++ b/crates/nuon/src/to.rs
@@ -204,7 +204,7 @@ fn value_to_string(
         },
         Value::Record { val, .. } => {
             let mut collection = vec![];
-            for (col, val) in &**val {
+            for (col, val) in val {
                 let col = if needs_quoting(col) {
                     &escape_quote_string(col)
                 } else {