diff --git a/docs/reference/query-languages/esql/images/functions/v_cosine.svg b/docs/reference/query-languages/esql/images/functions/v_cosine.svg
new file mode 100644
index 0000000000000..fb7a2ed91fa8d
--- /dev/null
+++ b/docs/reference/query-languages/esql/images/functions/v_cosine.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/v_cosine.json b/docs/reference/query-languages/esql/kibana/definition/functions/v_cosine.json
new file mode 100644
index 0000000000000..f3b3df1d88c6a
--- /dev/null
+++ b/docs/reference/query-languages/esql/kibana/definition/functions/v_cosine.json
@@ -0,0 +1,12 @@
+{
+ "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.",
+ "type" : "scalar",
+ "name" : "v_cosine",
+ "description" : "Calculates the cosine similarity between two dense_vectors.",
+ "signatures" : [ ],
+ "examples" : [
+ " from colors\n | where color != \"black\"\n | eval similarity = v_cosine(rgb_vector, [0, 255, 255])\n | sort similarity desc, color asc"
+ ],
+ "preview" : true,
+ "snapshot_only" : true
+}
diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/v_cosine.md b/docs/reference/query-languages/esql/kibana/docs/functions/v_cosine.md
new file mode 100644
index 0000000000000..22e4626fe38ad
--- /dev/null
+++ b/docs/reference/query-languages/esql/kibana/docs/functions/v_cosine.md
@@ -0,0 +1,11 @@
+% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.
+
+### V COSINE
+Calculates the cosine similarity between two dense_vectors.
+
+```esql
+ from colors
+ | where color != "black"
+ | eval similarity = v_cosine(rgb_vector, [0, 255, 255])
+ | sort similarity desc, color asc
+```
diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/vector-cosine-similarity.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/vector-cosine-similarity.csv-spec
new file mode 100644
index 0000000000000..d9e1ff408c739
--- /dev/null
+++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/vector-cosine-similarity.csv-spec
@@ -0,0 +1,93 @@
+ # Tests for cosine similarity function
+
+ similarityWithVectorField
+ required_capability: cosine_vector_similarity_function
+
+// tag::vector-cosine-similarity[]
+ from colors
+ | where color != "black"
+ | eval similarity = v_cosine(rgb_vector, [0, 255, 255])
+ | sort similarity desc, color asc
+// end::vector-cosine-similarity[]
+ | limit 10
+ | keep color, similarity
+ ;
+
+// tag::vector-cosine-similarity-result[]
+color:text | similarity:double
+cyan | 1.0
+teal | 1.0
+turquoise | 0.9890533685684204
+aqua marine | 0.964962363243103
+azure | 0.916246771812439
+lavender | 0.9136701822280884
+mint cream | 0.9122757911682129
+honeydew | 0.9122424125671387
+gainsboro | 0.9082483053207397
+gray | 0.9082483053207397
+// end::vector-cosine-similarity-result[]
+;
+
+ similarityAsPartOfExpression
+ required_capability: cosine_vector_similarity_function
+
+ from colors
+ | where color != "black"
+ | eval score = round((1 + v_cosine(rgb_vector, [0, 255, 255]) / 2), 3)
+ | sort score desc, color asc
+ | limit 10
+ | keep color, score
+ ;
+
+color:text | score:double
+cyan | 1.5
+teal | 1.5
+turquoise | 1.495
+aqua marine | 1.482
+azure | 1.458
+lavender | 1.457
+honeydew | 1.456
+mint cream | 1.456
+gainsboro | 1.454
+gray | 1.454
+;
+
+similarityWithLiteralVectors
+required_capability: cosine_vector_similarity_function
+
+row a = 1
+| eval similarity = round(v_cosine([1, 2, 3], [0, 1, 2]), 3)
+| keep similarity
+;
+
+similarity:double
+0.978
+;
+
+ similarityWithStats
+ required_capability: cosine_vector_similarity_function
+
+ from colors
+ | where color != "black"
+ | eval similarity = round(v_cosine(rgb_vector, [0, 255, 255]), 3)
+ | stats avg = round(avg(similarity), 3), min = min(similarity), max = max(similarity)
+ ;
+
+avg:double | min:double | max:double
+0.832 | 0.5 | 1.0
+;
+
+# TODO Need to implement a conversion function to convert a non-foldable row to a dense_vector
+similarityWithRow-Ignore
+required_capability: cosine_vector_similarity_function
+
+row vector = [1, 2, 3]
+| eval similarity = round(v_cosine(vector, [0, 1, 2]), 3)
+| sort similarity desc, color asc
+| limit 10
+| keep color, similarity
+;
+
+similarity:double
+0.978
+;
diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/vector/VectorSimilarityFunctionsIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/vector/VectorSimilarityFunctionsIT.java
new file mode 100644
index 0000000000000..6a861746facfd
--- /dev/null
+++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/vector/VectorSimilarityFunctionsIT.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.esql.vector;
+
+import com.carrotsearch.randomizedtesting.annotations.Name;
+import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
+
+import org.apache.lucene.index.VectorSimilarityFunction;
+import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.cluster.metadata.IndexMetadata;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.xcontent.XContentBuilder;
+import org.elasticsearch.xcontent.XContentFactory;
+import org.elasticsearch.xpack.esql.EsqlClientException;
+import org.elasticsearch.xpack.esql.EsqlTestUtils;
+import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase;
+import org.elasticsearch.xpack.esql.action.EsqlCapabilities;
+import org.junit.Before;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
+
+public class VectorSimilarityFunctionsIT extends AbstractEsqlIntegTestCase {
+
+ @ParametersFactory
+ public static Iterable