diff --git a/doc/sql/query.ebnf b/doc/sql/query.ebnf
index 6632d84c378d1b95b3f330e60e242fb8d3201091..30306b7959e5f3b78910e7a266a7fba8ad536517 100644
--- a/doc/sql/query.ebnf
+++ b/doc/sql/query.ebnf
@@ -70,6 +70,7 @@ type        ::= 'ANY'
                 | 'STRING'
                 | 'TEXT'
                 | 'UNSIGNED'
+                | 'UUID'
                 | 'VARCHAR' ('(' length ')')?
 parameter   ::= '$' unsigned | '?'
 delete      ::= 'DELETE' 'FROM' table ('WHERE' expression)?
diff --git a/sbroad-cartridge/test_app/test/data/config.yml b/sbroad-cartridge/test_app/test/data/config.yml
index 7bfe4c14708cd088f816b692cccb9b5fadcb11fa..d6dbe23269b2bf7d6084d8829559a71604608864 100644
--- a/sbroad-cartridge/test_app/test/data/config.yml
+++ b/sbroad-cartridge/test_app/test/data/config.yml
@@ -1372,3 +1372,34 @@ schema:
       engine: memtx
       sharding_key:
         - id
+    uuid_t:
+      format:
+        - type: uuid
+          name: id
+          is_nullable: false
+        - type: string
+          name: name
+          is_nullable: false
+        - type: unsigned
+          name: bucket_id
+          is_nullable: false
+      temporary: false
+      indexes:
+        - unique: true
+          parts:
+            - path: id
+              is_nullable: false
+              type: uuid
+          type: TREE
+          name: primary
+        - unique: false
+          parts:
+            - path: bucket_id
+              is_nullable: false
+              type: unsigned
+          type: TREE
+          name: bucket_id
+      is_local: false
+      engine: memtx
+      sharding_key:
+        - id
diff --git a/sbroad-cartridge/test_app/test/integration/uuid_test.lua b/sbroad-cartridge/test_app/test/integration/uuid_test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..2a64c8e8595445adfbda516f0395c0b1ff7748ee
--- /dev/null
+++ b/sbroad-cartridge/test_app/test/integration/uuid_test.lua
@@ -0,0 +1,126 @@
+local t = require('luatest')
+local g = t.group('integration_api.insert_uuid_sql')
+
+local helper = require('test.helper.cluster_no_replication')
+
+local UUID = require("uuid")
+local uuid1 = UUID()
+local uuid2 = UUID()
+local uuid3 = "fb1649a4-d2db-4df4-a24d-2b4e81ee8a41"
+
+g.before_all(
+        function()
+            helper.start_test_cluster(helper.cluster_config)
+
+            local api = helper.cluster:server("api-1").net_box
+
+            local r, err = api:call("sbroad.execute",
+                    {
+                        [[
+                            INSERT INTO "uuid_t"("id", "name")
+                            VALUES (?, ?), (?, ?), (?, ?)
+                        ]],
+                        { uuid1, "test-1", uuid2, "test-2", uuid3, "test-3" }
+                    }
+            )
+            t.assert_equals(err, nil)
+            t.assert_equals(r, {row_count = 3})
+        end
+)
+
+g.after_all(function()
+    helper.stop_test_cluster()
+end)
+
+g.test_uuid_sql_where_uuid1 = function ()
+    local api = helper.cluster:server("api-1").net_box
+
+    local r, err = api:call("sbroad.execute",
+            {
+                [[SELECT "id", "name" FROM "uuid_t" WHERE "id" = ?]],
+                {uuid1}
+            }
+    )
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            {name = "id", type = "uuid"},
+            {name = "name", type = "string"},
+        },
+        rows = {
+            { uuid1, 'test-1' }
+        },
+    })
+end
+
+g.test_uuid_sql_where_cast_uuid_test1 = function ()
+    local api = helper.cluster:server("api-1").net_box
+
+    local r, err = api:call(
+            "sbroad.execute",
+            {
+                [[SELECT CAST("id" as Text) as "id", "name" FROM "uuid_t" WHERE "id" = ? ]],
+                { uuid1 }
+            }
+    )
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            {name = "id", type = "string"},
+            {name = "name", type = "string"},
+        },
+        rows = {
+            { string.format('%s', uuid1), 'test-1' }
+        },
+    })
+end
+
+g.test_uuid_sql_where_cast_uuid_test2 = function ()
+    local api = helper.cluster:server("api-1").net_box
+
+    local r, err = api:call("sbroad.execute",
+            {
+                [[SELECT * FROM "uuid_t" WHERE CAST("id" as Text) IN (?) ]],
+                { uuid3 }
+            }
+    )
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            {name = "id", type = "uuid"},
+            {name = "name", type = "string"},
+        },
+        rows = {
+            { uuid3, 'test-3' }
+        },
+    })
+end
+
+g.test_uuid_sql_where_cast_uuid_test3 = function ()
+    local api = helper.cluster:server("api-1").net_box
+
+    local r, err = api:call(
+            "sbroad.execute",
+            {
+                [[
+                    SELECT CAST("id" as Uuid) as "id", "name"
+                    FROM (
+                        SELECT CAST("id" as Text) as "id", "name"
+                        FROM "uuid_t" where "id" = ?
+                    )
+                ]],
+                { uuid2 }
+            }
+    )
+
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            {name = "id", type = "uuid"},
+            {name = "name", type = "string"},
+        },
+        rows = {
+            { uuid2, 'test-2' }
+        },
+    })
+end
diff --git a/sbroad-core/src/cbo/selectivity.rs b/sbroad-core/src/cbo/selectivity.rs
index 9672f8ce06408f85076037b0a39ac3ffdd263593..c4ca2e9e2a25f6221aaf350d9beef9503755ebdf 100644
--- a/sbroad-core/src/cbo/selectivity.rs
+++ b/sbroad-core/src/cbo/selectivity.rs
@@ -338,6 +338,9 @@ pub fn calculate_filter_selectivity(
                 "Unable to calculate selectivity for array type column",
             )),
         )),
+        Type::Uuid => {
+            todo!("Don't know what to do here")
+        }
     }
 }
 
diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs
index 689fb9a4df774fa1fe44b46728f909bb47c3b832..e96d8c1ccb9aaf04dc9a9d4ea1f5e96dc755375d 100644
--- a/sbroad-core/src/frontend/sql.rs
+++ b/sbroad-core/src/frontend/sql.rs
@@ -157,6 +157,7 @@ fn parse_proc_params(
             Rule::TypeNumber => RelationType::Number,
             Rule::TypeScalar => RelationType::Scalar,
             Rule::TypeString | Rule::TypeText | Rule::TypeVarchar => RelationType::String,
+            Rule::TypeUuid => RelationType::Uuid,
             Rule::TypeUnsigned => RelationType::Unsigned,
             _ => unreachable!("Unexpected node: {type_node:?}"),
         };
@@ -384,6 +385,9 @@ fn parse_create_table(ast: &AbstractSyntaxTree, node: &ParseNode) -> Result<Ddl,
                                     Rule::TypeUnsigned => {
                                         column_def.data_type = RelationType::Unsigned;
                                     }
+                                    Rule::TypeUuid => {
+                                        column_def.data_type = RelationType::Uuid;
+                                    }
                                     _ => {
                                         return Err(SbroadError::Invalid(
                                             Entity::Node,
diff --git a/sbroad-core/src/frontend/sql/query.pest b/sbroad-core/src/frontend/sql/query.pest
index ae0fd58c0e8e885e3352101379ef30b574e44968..c394039a908d8d7f8b6152cab1e19e25ceb0eef7 100644
--- a/sbroad-core/src/frontend/sql/query.pest
+++ b/sbroad-core/src/frontend/sql/query.pest
@@ -107,7 +107,7 @@ Query = { (SelectWithOptionalContinuation | Values | Insert | Update | Delete) ~
         UnionAllContinuation = { ^"union" ~ ^"all" ~ Select }
     Select = {
         ^"select" ~ Projection ~ ^"from" ~ Scan ~
-        Join? ~ WhereClause? ~ 
+        Join? ~ WhereClause? ~
         (^"group" ~ ^"by" ~ GroupBy)? ~
         (^"having" ~ Having)?
     }
@@ -203,7 +203,7 @@ Expr = { ExprAtomValue ~ (ExprInfixOp ~ ExprAtomValue)* }
             Cast = { ^"cast" ~ "(" ~ Expr ~ ^"as" ~ TypeCast ~ ")" }
                 TypeCast = _{ TypeAny | ColumnDefType }
                 ColumnDefType = { TypeBool | TypeDecimal | TypeDouble | TypeInt | TypeNumber
-                                   | TypeScalar | TypeString | TypeText | TypeUnsigned | TypeVarchar }
+                                   | TypeScalar | TypeString | TypeText | TypeUnsigned | TypeVarchar | TypeUuid }
                     TypeAny = { ^"any" }
                     TypeBool = { (^"boolean" | ^"bool") }
                     TypeDecimal = { ^"decimal" }
@@ -213,6 +213,7 @@ Expr = { ExprAtomValue ~ (ExprInfixOp ~ ExprAtomValue)* }
                     TypeScalar = { ^"scalar" }
                     TypeString = { ^"string" }
                     TypeText = { ^"text" }
+                    TypeUuid = { ^"uuid" }
                     TypeUnsigned = { ^"unsigned" }
                     TypeVarchar = { ^"varchar" ~ "(" ~ Unsigned ~ ")" }
             UnaryOperator = _{ Exists }
diff --git a/sbroad-core/src/ir/expression/cast.rs b/sbroad-core/src/ir/expression/cast.rs
index dc1aa03e6778b75e37ffcc22625f560d7702a060..8e4269c35871306b24e95f38169a0bbeb4e7b02a 100644
--- a/sbroad-core/src/ir/expression/cast.rs
+++ b/sbroad-core/src/ir/expression/cast.rs
@@ -19,6 +19,7 @@ pub enum Type {
     Scalar,
     String,
     Text,
+    Uuid,
     Unsigned,
     Varchar(usize),
 }
@@ -40,6 +41,7 @@ impl TryFrom<&Rule> for Type {
             Rule::TypeScalar => Ok(Type::Scalar),
             Rule::TypeString => Ok(Type::String),
             Rule::TypeText => Ok(Type::Text),
+            Rule::TypeUuid => Ok(Type::Uuid),
             Rule::TypeUnsigned => Ok(Type::Unsigned),
             _ => Err(SbroadError::Unsupported(
                 Entity::Type,
@@ -64,6 +66,7 @@ impl TryFrom<&RelationType> for Type {
             RelationType::Unsigned => Ok(Type::Unsigned),
             RelationType::Map => Ok(Type::Map),
             RelationType::Any => Ok(Type::Any),
+            RelationType::Uuid => Ok(Type::Uuid),
             RelationType::Array => Err(SbroadError::Unsupported(
                 Entity::Type,
                 Some("array int the cast operation".to_string()),
@@ -85,6 +88,7 @@ impl From<&Type> for String {
             Type::Scalar => "scalar".to_string(),
             Type::String => "string".to_string(),
             Type::Text => "text".to_string(),
+            Type::Uuid => "uuid".to_string(),
             Type::Unsigned => "unsigned".to_string(),
             Type::Varchar(length) => format!("varchar({length})"),
         }
@@ -108,6 +112,7 @@ impl Type {
             Type::Double => RelationType::Double,
             Type::Integer => RelationType::Integer,
             Type::Number => RelationType::Number,
+            Type::Uuid => RelationType::Uuid,
             Type::String | Type::Text | Type::Varchar(_) => RelationType::String,
             Type::Unsigned => RelationType::Unsigned,
         }
diff --git a/sbroad-core/src/ir/relation.rs b/sbroad-core/src/ir/relation.rs
index 49eff9ec79df6bb4d37cf32bdfcc4e5d01ec88d3..9ae2e0836cc0931a04709e0b137c67e25923e3da 100644
--- a/sbroad-core/src/ir/relation.rs
+++ b/sbroad-core/src/ir/relation.rs
@@ -42,6 +42,7 @@ pub enum Type {
     Scalar,
     String,
     Number,
+    Uuid,
     Unsigned,
 }
 
@@ -56,6 +57,7 @@ impl fmt::Display for Type {
             Type::Scalar => write!(f, "scalar"),
             Type::String => write!(f, "string"),
             Type::Number => write!(f, "number"),
+            Type::Uuid => write!(f, "uuid"),
             Type::Unsigned => write!(f, "unsigned"),
             Type::Any => write!(f, "any"),
             Type::Map => write!(f, "map"),
@@ -72,6 +74,7 @@ impl From<&Type> for FieldType {
             Type::Integer => FieldType::Integer,
             Type::Number => FieldType::Number,
             Type::Scalar => FieldType::Scalar,
+            Type::Uuid => FieldType::Uuid,
             Type::String => FieldType::String,
             Type::Unsigned => FieldType::Unsigned,
             Type::Array => FieldType::Array,
@@ -91,6 +94,7 @@ impl From<&Type> for SpaceFieldType {
             Type::Number => SpaceFieldType::Number,
             Type::Scalar => SpaceFieldType::Scalar,
             Type::String => SpaceFieldType::String,
+            Type::Uuid => SpaceFieldType::Uuid,
             Type::Unsigned => SpaceFieldType::Unsigned,
             Type::Array => SpaceFieldType::Array,
             Type::Any => SpaceFieldType::Any,
@@ -142,6 +146,7 @@ impl Type {
             "number" => Ok(Type::Number),
             "scalar" => Ok(Type::Scalar),
             "string" | "text" => Ok(Type::String),
+            "uuid" => Ok(Type::Uuid),
             "unsigned" => Ok(Type::Unsigned),
             "array" => Ok(Type::Array),
             "any" => Ok(Type::Any),
@@ -158,7 +163,7 @@ impl Type {
     pub fn new_from_possibly_incorrect(s: &str) -> Result<Self, SbroadError> {
         match s.to_string().to_lowercase().as_str() {
             "boolean" | "decimal" | "double" | "integer" | "number" | "numeric" | "scalar"
-            | "string" | "text" | "unsigned" => Ok(Type::Scalar),
+            | "string" | "uuid" | "text" | "unsigned" => Ok(Type::Scalar),
             "array" => Ok(Type::Array),
             "map" => Ok(Type::Map),
             "any" => Ok(Type::Any),
@@ -182,6 +187,7 @@ impl Type {
                 | Type::Number
                 | Type::Scalar
                 | Type::String
+                | Type::Uuid
                 | Type::Unsigned
         )
     }
@@ -198,7 +204,7 @@ impl Type {
                     Type::Double | Type::Integer | Type::Unsigned | Type::Decimal | Type::Number,
                 )
                 | (Type::Scalar, Type::Scalar)
-                | (Type::String, Type::String)
+                | (Type::String | Type::Uuid, Type::String | Type::Uuid)
         )
     }
 }
@@ -248,6 +254,7 @@ impl From<Column> for Field {
             Type::Number => Field::number(column.name),
             Type::Scalar => Field::scalar(column.name),
             Type::String => Field::string(column.name),
+            Type::Uuid => Field::uuid(column.name),
             Type::Unsigned => Field::unsigned(column.name),
             Type::Array => Field::array(column.name),
             Type::Any => Field::any(column.name),
@@ -286,6 +293,7 @@ impl SerSerialize for Column {
             Type::Number => map.serialize_entry("type", "number")?,
             Type::Scalar => map.serialize_entry("type", "scalar")?,
             Type::String => map.serialize_entry("type", "string")?,
+            Type::Uuid => map.serialize_entry("type", "uuid")?,
             Type::Unsigned => map.serialize_entry("type", "unsigned")?,
             Type::Array => map.serialize_entry("type", "array")?,
             Type::Any => map.serialize_entry("type", "any")?,
@@ -349,6 +357,7 @@ impl<'de> Visitor<'de> for ColumnVisitor {
             }
             "unsigned" => Ok(Column::new(&column_name, Type::Unsigned, role, is_nullable)),
             "array" => Ok(Column::new(&column_name, Type::Array, role, is_nullable)),
+            "uuid" => Ok(Column::new(&column_name, Type::Uuid, role, is_nullable)),
             _ => Err(Error::custom("unsupported column type")),
         }
     }
diff --git a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
index 8581dce8281711d1d4556f8e36d89970cd8683a6..f1cf25a1678935bdccdefee136bef8fc4f41b85a 100644
--- a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
+++ b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
@@ -107,8 +107,8 @@ fn equality_propagation5() {
             r#"SELECT "t"."a" FROM "t""#,
             r#"WHERE ("t"."d") = (?) and ("t"."c") = (?)"#,
             r#"and ("t"."a") = (?) and ("t"."b") = (?)"#,
-            r#"and ("t"."c") = ("t"."b") and ("t"."b") = ("t"."a")"#,
-            r#"and ("t"."a") = ("t"."d")"#,
+            r#"and ("t"."c") = ("t"."d") and ("t"."d") = ("t"."b")"#,
+            r#"and ("t"."b") = ("t"."a")"#,
         ),
         vec![
             Value::from(1_u64),
diff --git a/sbroad-core/src/ir/value.rs b/sbroad-core/src/ir/value.rs
index 1151ff201dc4d608a66074324ed145ea856cf3b9..bd7addf4b163cc3e6fca004989bdec8873d34abc 100644
--- a/sbroad-core/src/ir/value.rs
+++ b/sbroad-core/src/ir/value.rs
@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
 use tarantool::decimal::Decimal;
 use tarantool::tlua::{self, LuaRead};
 use tarantool::tuple::{FieldType, KeyDefPart};
+use tarantool::uuid::Uuid;
 
 use crate::error;
 use crate::errors::{Action, Entity, SbroadError};
@@ -130,6 +131,8 @@ pub enum Value {
     Unsigned(u64),
     /// Tuple type
     Tuple(Tuple),
+    /// Uuid type
+    Uuid(Uuid),
 }
 
 /// Custom Ordering using Trivalent instead of simple Equal.
@@ -185,6 +188,7 @@ impl fmt::Display for Value {
             Value::Decimal(v) => fmt::Display::fmt(v, f),
             Value::String(v) => write!(f, "'{v}'"),
             Value::Tuple(v) => write!(f, "{v}"),
+            Value::Uuid(v) => fmt::Display::fmt(v, f),
         }
     }
 }
@@ -275,6 +279,12 @@ impl From<Trivalent> for Value {
     }
 }
 
+impl From<Uuid> for Value {
+    fn from(v: Uuid) -> Self {
+        Value::Uuid(v)
+    }
+}
+
 /// Helper function to extract inner numerical value from `value` and cast it to `Decimal`.
 ///
 /// # Errors
@@ -439,11 +449,14 @@ impl Value {
                 | Value::Decimal(_)
                 | Value::Double(_)
                 | Value::String(_)
+                | Value::Uuid(_)
                 | Value::Tuple(_) => Trivalent::False,
             },
             Value::Null => Trivalent::Unknown,
             Value::Integer(s) => match other {
-                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) => Trivalent::False,
+                Value::Boolean(_) | Value::String(_) | Value::Uuid(_) | Value::Tuple(_) => {
+                    Trivalent::False
+                }
                 Value::Null => Trivalent::Unknown,
                 Value::Integer(o) => (s == o).into(),
                 Value::Decimal(o) => (&Decimal::from(*s) == o).into(),
@@ -454,7 +467,9 @@ impl Value {
                 Value::Unsigned(o) => (&Decimal::from(*s) == o).into(),
             },
             Value::Double(s) => match other {
-                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) => Trivalent::False,
+                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) | Value::Uuid(_) => {
+                    Trivalent::False
+                }
                 Value::Null => Trivalent::Unknown,
                 Value::Integer(o) => (*s == Double::from(*o)).into(),
                 // If double can't be converted to decimal without error then it is not equal to decimal.
@@ -466,7 +481,9 @@ impl Value {
                 }
             },
             Value::Decimal(s) => match other {
-                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) => Trivalent::False,
+                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) | Value::Uuid(_) => {
+                    Trivalent::False
+                }
                 Value::Null => Trivalent::Unknown,
                 Value::Integer(o) => (s == &Decimal::from(*o)).into(),
                 Value::Decimal(o) => (s == o).into(),
@@ -475,7 +492,9 @@ impl Value {
                 Value::Unsigned(o) => (s == &Decimal::from(*o)).into(),
             },
             Value::Unsigned(s) => match other {
-                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) => Trivalent::False,
+                Value::Boolean(_) | Value::String(_) | Value::Uuid(_) | Value::Tuple(_) => {
+                    Trivalent::False
+                }
                 Value::Null => Trivalent::Unknown,
                 Value::Integer(o) => (Decimal::from(*s) == *o).into(),
                 Value::Decimal(o) => (&Decimal::from(*s) == o).into(),
@@ -491,6 +510,7 @@ impl Value {
                 | Value::Decimal(_)
                 | Value::Double(_)
                 | Value::Unsigned(_)
+                | Value::Uuid(_)
                 | Value::Tuple(_) => Trivalent::False,
                 Value::Null => Trivalent::Unknown,
                 Value::String(o) => s.eq(o).into(),
@@ -502,8 +522,20 @@ impl Value {
                 | Value::Double(_)
                 | Value::Unsigned(_)
                 | Value::String(_)
+                | Value::Uuid(_)
+                | Value::Tuple(_) => Trivalent::False,
+                Value::Null => Trivalent::Unknown,
+            },
+            Value::Uuid(s) => match other {
+                Value::Boolean(_)
+                | Value::Integer(_)
+                | Value::Decimal(_)
+                | Value::Double(_)
+                | Value::String(_)
+                | Value::Unsigned(_)
                 | Value::Tuple(_) => Trivalent::False,
                 Value::Null => Trivalent::Unknown,
+                Value::Uuid(o) => s.eq(o).into(),
             },
         }
     }
@@ -518,6 +550,7 @@ impl Value {
             Value::Unsigned(_) => FieldType::Unsigned,
             Value::String(_) => FieldType::String,
             Value::Tuple(_) => FieldType::Array,
+            Value::Uuid(_) => FieldType::Uuid,
             Value::Null => FieldType::Any,
         };
         KeyDefPart {
@@ -529,6 +562,149 @@ impl Value {
         }
     }
 
+    /// Compares two values.
+    /// The result uses four-valued logic (standard `Ordering` variants and
+    /// `Unknown` in case `Null` was met).
+    ///
+    /// Returns `None` in case of
+    /// * String casting Error or types mismatch.
+    /// * Float `NaN` comparison occurred.
+    #[must_use]
+    #[allow(clippy::too_many_lines)]
+    pub fn partial_cmp(&self, other: &Value) -> Option<TrivalentOrdering> {
+        match self {
+            Value::Boolean(s) => match other {
+                Value::Boolean(o) => TrivalentOrdering::from(s.cmp(o)).into(),
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Unsigned(_)
+                | Value::Integer(_)
+                | Value::Decimal(_)
+                | Value::Double(_)
+                | Value::String(_)
+                | Value::Uuid(_)
+                | Value::Tuple(_) => None,
+            },
+            Value::Null => TrivalentOrdering::Unknown.into(),
+            Value::Integer(s) => match other {
+                Value::Boolean(_) | Value::String(_) | Value::Uuid(_) | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Integer(o) => TrivalentOrdering::from(s.cmp(o)).into(),
+                Value::Decimal(o) => TrivalentOrdering::from(Decimal::from(*s).cmp(o)).into(),
+                // If double can't be converted to decimal without error then it is not equal to integer.
+                Value::Double(o) => {
+                    let self_converted = Decimal::from_str(&format!("{s}"));
+                    let other_converted = Decimal::from_str(&format!("{o}"));
+                    match (self_converted, other_converted) {
+                        (Ok(d1), Ok(d2)) => TrivalentOrdering::from(d1.cmp(&d2)).into(),
+                        _ => None,
+                    }
+                }
+                Value::Unsigned(o) => {
+                    TrivalentOrdering::from(Decimal::from(*s).cmp(&Decimal::from(*o))).into()
+                }
+            },
+            Value::Double(s) => match other {
+                Value::Boolean(_) | Value::String(_) | Value::Tuple(_) | Value::Uuid(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Integer(o) => {
+                    if let Some(ord) = s.partial_cmp(&Double::from(*o)) {
+                        TrivalentOrdering::from(ord).into()
+                    } else {
+                        None
+                    }
+                }
+                // If double can't be converted to decimal without error then it is not equal to decimal.
+                Value::Decimal(o) => {
+                    if let Ok(d) = Decimal::from_str(&format!("{s}")) {
+                        TrivalentOrdering::from(d.cmp(o)).into()
+                    } else {
+                        None
+                    }
+                }
+                Value::Double(o) => {
+                    if let Some(ord) = s.partial_cmp(o) {
+                        TrivalentOrdering::from(ord).into()
+                    } else {
+                        None
+                    }
+                }
+                // If double can't be converted to decimal without error then it is not equal to unsigned.
+                Value::Unsigned(o) => {
+                    if let Ok(d) = Decimal::from_str(&format!("{s}")) {
+                        TrivalentOrdering::from(d.cmp(&Decimal::from(*o))).into()
+                    } else {
+                        None
+                    }
+                }
+            },
+            Value::Decimal(s) => match other {
+                Value::Boolean(_) | Value::String(_) | Value::Uuid(_) | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Integer(o) => TrivalentOrdering::from(s.cmp(&Decimal::from(*o))).into(),
+                Value::Decimal(o) => TrivalentOrdering::from(s.cmp(o)).into(),
+                // If double can't be converted to decimal without error then it is not equal to decimal.
+                Value::Double(o) => {
+                    if let Ok(d) = Decimal::from_str(&format!("{o}")) {
+                        TrivalentOrdering::from(s.cmp(&d)).into()
+                    } else {
+                        None
+                    }
+                }
+                Value::Unsigned(o) => TrivalentOrdering::from(s.cmp(&Decimal::from(*o))).into(),
+            },
+            Value::Unsigned(s) => match other {
+                Value::Boolean(_) | Value::String(_) | Value::Uuid(_) | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Integer(o) => {
+                    TrivalentOrdering::from(Decimal::from(*s).cmp(&Decimal::from(*o))).into()
+                }
+                Value::Decimal(o) => TrivalentOrdering::from(Decimal::from(*s).cmp(o)).into(),
+                // If double can't be converted to decimal without error then it is not equal to unsigned.
+                Value::Double(o) => {
+                    if let Ok(d) = Decimal::from_str(&format!("{o}")) {
+                        TrivalentOrdering::from(Decimal::from(*s).cmp(&d)).into()
+                    } else {
+                        None
+                    }
+                }
+                Value::Unsigned(o) => TrivalentOrdering::from(s.cmp(o)).into(),
+            },
+            Value::String(s) => match other {
+                Value::Boolean(_)
+                | Value::Integer(_)
+                | Value::Decimal(_)
+                | Value::Double(_)
+                | Value::Unsigned(_)
+                | Value::Uuid(_)
+                | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::String(o) => TrivalentOrdering::from(s.cmp(o)).into(),
+            },
+            Value::Uuid(u) => match other {
+                Value::Boolean(_)
+                | Value::Integer(_)
+                | Value::Decimal(_)
+                | Value::Double(_)
+                | Value::Unsigned(_)
+                | Value::String(_)
+                | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+                Value::Uuid(o) => TrivalentOrdering::from(u.cmp(o)).into(),
+            },
+            Value::Tuple(_) => match other {
+                Value::Boolean(_)
+                | Value::Integer(_)
+                | Value::Decimal(_)
+                | Value::Double(_)
+                | Value::Unsigned(_)
+                | Value::String(_)
+                | Value::Uuid(_)
+                | Value::Tuple(_) => None,
+                Value::Null => TrivalentOrdering::Unknown.into(),
+            },
+        }
+    }
+
     /// Cast a value to a different type and wrap into encoded value.
     /// If the target type is the same as the current type, the value
     /// is returned by reference. Otherwise, the value is cloned.
@@ -647,6 +823,23 @@ impl Value {
                     format!("{self:?} into string"),
                 )),
             },
+            Type::Uuid => match self {
+                Value::Uuid(_) => Ok(self.into()),
+                Value::String(v) => Ok(Value::Uuid(Uuid::parse_str(v).map_err(|e| {
+                    SbroadError::FailedTo(
+                        Action::Serialize,
+                        Some(Entity::Value),
+                        format!("uuid {v} into string: {e}"),
+                    )
+                })?)
+                .into()),
+                Value::Null => Ok(Value::Null.into()),
+                _ => Err(SbroadError::FailedTo(
+                    Action::Serialize,
+                    Some(Entity::Value),
+                    format!("{self:?} into uuid"),
+                )),
+            },
             Type::Number => match self {
                 Value::Integer(_) | Value::Decimal(_) | Value::Double(_) | Value::Unsigned(_) => {
                     Ok(self.into())
@@ -708,6 +901,7 @@ impl Value {
             Value::Boolean(_) => Type::Boolean,
             Value::String(_) => Type::String,
             Value::Tuple(_) => Type::Array,
+            Value::Uuid(_) => Type::Uuid,
             Value::Null => Type::Scalar,
         }
     }
@@ -728,6 +922,7 @@ impl ToHashString for Value {
             Value::Boolean(v) => v.to_string(),
             Value::String(v) => v.to_string(),
             Value::Tuple(v) => v.to_string(),
+            Value::Uuid(v) => v.to_string(),
             Value::Null => "NULL".to_string(),
         }
     }
@@ -777,6 +972,7 @@ pub enum MsgPackValue<'v> {
     Unsigned(&'v u64),
     String(&'v String),
     Tuple(&'v Tuple),
+    Uuid(&'v Uuid),
     Null(()),
 }
 
@@ -790,6 +986,7 @@ impl<'v> From<&'v Value> for MsgPackValue<'v> {
             Value::Null => MsgPackValue::Null(()),
             Value::String(v) => MsgPackValue::String(v),
             Value::Tuple(v) => MsgPackValue::Tuple(v),
+            Value::Uuid(v) => MsgPackValue::Uuid(v),
             Value::Unsigned(v) => MsgPackValue::Unsigned(v),
         }
     }
@@ -805,6 +1002,7 @@ pub enum LuaValue {
     Integer(i64),
     Unsigned(u64),
     String(String),
+    Uuid(Uuid),
     Tuple(Tuple),
     Null(()),
 }
@@ -819,6 +1017,7 @@ impl fmt::Display for LuaValue {
             LuaValue::Unsigned(v) => write!(f, "{v}"),
             LuaValue::String(v) => write!(f, "'{v}'"),
             LuaValue::Tuple(v) => write!(f, "{v}"),
+            LuaValue::Uuid(v) => write!(f, "{v}"),
             LuaValue::Null(()) => write!(f, "NULL"),
         }
     }
@@ -834,6 +1033,7 @@ impl From<Value> for LuaValue {
             Value::Null => LuaValue::Null(()),
             Value::String(v) => LuaValue::String(v),
             Value::Tuple(v) => LuaValue::Tuple(v),
+            Value::Uuid(v) => LuaValue::Uuid(v),
             Value::Unsigned(v) => LuaValue::Unsigned(v),
         }
     }
@@ -861,6 +1061,7 @@ impl From<LuaValue> for Value {
             LuaValue::Boolean(v) => Value::Boolean(v),
             LuaValue::String(v) => Value::String(v),
             LuaValue::Tuple(v) => Value::Tuple(v),
+            LuaValue::Uuid(v) => Value::Uuid(v),
             LuaValue::Null(()) => Value::Null,
         }
     }
@@ -876,6 +1077,7 @@ impl From<Value> for String {
             Value::Boolean(v) => v.to_string(),
             Value::String(v) => v,
             Value::Tuple(v) => v.to_string(),
+            Value::Uuid(v) => v.to_string(),
             Value::Null => "NULL".to_string(),
         }
     }
@@ -893,6 +1095,7 @@ impl<L: tlua::AsLua> tlua::Push<L> for Value {
             Value::Boolean(v) => v.push_to_lua(lua),
             Value::String(v) => v.push_to_lua(lua),
             Value::Tuple(v) => v.push_to_lua(lua),
+            Value::Uuid(v) => v.push_to_lua(lua),
             Value::Null => tlua::Null.push_to_lua(lua),
         }
     }
@@ -913,6 +1116,7 @@ where
             Value::Boolean(v) => v.push_into_lua(lua),
             Value::String(v) => v.push_into_lua(lua),
             Value::Tuple(v) => v.push_into_lua(lua),
+            Value::Uuid(v) => v.push_into_lua(lua),
             Value::Null => tlua::Null.push_into_lua(lua),
         }
     }
@@ -970,6 +1174,10 @@ where
             Ok(v) => return Ok(Self::Tuple(v)),
             Err((lua, _)) => lua,
         };
+        let lua = match tlua::LuaRead::lua_read_at_position(lua, index) {
+            Ok(v) => return Ok(Self::Uuid(v)),
+            Err((lua, _)) => lua,
+        };
         let Err((lua, _)) = tlua::Null::lua_read_at_position(lua, index) else {
             return Ok(Self::Null);
         };
diff --git a/sbroad-core/src/ir/value/tests.rs b/sbroad-core/src/ir/value/tests.rs
index bda293b4aec4c3941a15b289def1714d35758fe7..20286e472aff357f64fcd194240c91f4b429f2d4 100644
--- a/sbroad-core/src/ir/value/tests.rs
+++ b/sbroad-core/src/ir/value/tests.rs
@@ -9,6 +9,49 @@ fn boolean() {
     assert_ne!(Value::from(true), Value::from(false));
 }
 
+#[test]
+fn uuid() {
+    let uid = uuid::Uuid::new_v4();
+    let t_uid_1 = Uuid::parse_str(&uid.to_string()).unwrap();
+    let t_uid_2 = Uuid::parse_str(&uuid::Uuid::new_v4().to_string()).unwrap();
+    let v_uid = Value::Uuid(t_uid_1);
+
+    assert_eq!(Value::from(t_uid_1), v_uid);
+    assert_eq!(format!("{}", v_uid), uid.to_string());
+    assert_eq!(v_uid.get_type(), Type::Uuid);
+    assert_eq!(v_uid.eq(&Value::Uuid(t_uid_1)), Trivalent::True);
+    assert_eq!(v_uid.eq(&Value::Uuid(t_uid_2)), Trivalent::False);
+    assert_eq!(
+        v_uid.eq(&Value::String(t_uid_1.to_string())),
+        Trivalent::False
+    );
+    assert_eq!(
+        v_uid.partial_cmp(&Value::Uuid(t_uid_1)),
+        Some(TrivalentOrdering::Equal)
+    );
+    assert_ne!(
+        v_uid.partial_cmp(&Value::Uuid(t_uid_2)),
+        Some(TrivalentOrdering::Equal)
+    );
+    assert_eq!(
+        Value::String(uid.to_string()).cast(&Type::Uuid).is_ok(),
+        true
+    );
+    assert_eq!(v_uid.partial_cmp(&Value::String(t_uid_2.to_string())), None);
+}
+
+fn uuid_negative() {
+    assert_eq!(
+        Value::String("hello".to_string())
+            .cast(&Type::Uuid)
+            .unwrap_err(),
+        SbroadError::FailedTo(
+            Action::Serialize,
+            Some(Entity::Value),
+            "uuid hello into string: invalid length: expected one of [36, 32], found 5".to_string()
+        )
+    );
+}
 #[test]
 fn decimal() {
     assert_eq!(