diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java
index 47addc84a..239f7e1ef 100644
--- a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java
+++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java
@@ -35,6 +35,7 @@
import org.apache.geaflow.dsl.planner.GQLJavaTypeFactory;
import org.apache.geaflow.dsl.schema.GeaFlowFunction;
import org.apache.geaflow.dsl.udf.graph.AllSourceShortestPath;
+import org.apache.geaflow.dsl.udf.graph.BetweennessCentrality;
import org.apache.geaflow.dsl.udf.graph.ClosenessCentrality;
import org.apache.geaflow.dsl.udf.graph.ClusterCoefficient;
import org.apache.geaflow.dsl.udf.graph.CommonNeighbors;
@@ -231,6 +232,7 @@ public class BuildInSqlFunctionTable extends ListSqlOperatorTable {
.add(GeaFlowFunction.of(IncrementalKCore.class))
.add(GeaFlowFunction.of(IncMinimumSpanningTree.class))
.add(GeaFlowFunction.of(ClosenessCentrality.class))
+ .add(GeaFlowFunction.of(BetweennessCentrality.class))
.add(GeaFlowFunction.of(WeakConnectedComponents.class))
.add(GeaFlowFunction.of(TriangleCount.class))
.add(GeaFlowFunction.of(ClusterCoefficient.class))
diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/BetweennessCentrality.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/BetweennessCentrality.java
new file mode 100644
index 000000000..c712bdb24
--- /dev/null
+++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/BetweennessCentrality.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geaflow.dsl.udf.graph;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.geaflow.common.type.primitive.DoubleType;
+import org.apache.geaflow.dsl.common.algo.AlgorithmRuntimeContext;
+import org.apache.geaflow.dsl.common.algo.AlgorithmUserFunction;
+import org.apache.geaflow.dsl.common.data.Row;
+import org.apache.geaflow.dsl.common.data.RowEdge;
+import org.apache.geaflow.dsl.common.data.RowVertex;
+import org.apache.geaflow.dsl.common.data.impl.ObjectRow;
+import org.apache.geaflow.dsl.common.function.Description;
+import org.apache.geaflow.dsl.common.types.GraphSchema;
+import org.apache.geaflow.dsl.common.types.StructType;
+import org.apache.geaflow.dsl.common.types.TableField;
+import org.apache.geaflow.model.graph.edge.EdgeDirection;
+
+/**
+ * Built-in UDGA computing Betweenness Centrality via a vertex-centric
+ * adaptation of Brandes' algorithm.
+ *
+ *
All vertices act as sources simultaneously. Each vertex keeps per-source
+ * state {@code st[source] = [dist, sigma, delta, childCount, respCount,
+ * recvChild, pendingSum, forwarded, backwardDone]} plus its per-source
+ * predecessor list.
+ *
+ *
Phase 1 (forward): a BFS from every source counts the number of shortest
+ * paths ({@code sigma}) reaching each vertex and records predecessors. Every
+ * forwarded neighbour replies ACK (it is a child) or NACK (it is not), so a
+ * vertex learns how many children it has without a global barrier.
+ *
+ *
Phase 2 (backward): once a vertex has heard from all children for a source
+ * it finalizes its dependency {@code delta = sigma * sum((1 + delta_child) /
+ * sigma_child)}, adds it to its betweenness score, and pushes the contribution
+ * to its predecessors.
+ *
+ *
Directed, unnormalized betweenness (endpoints excluded). Complexity is
+ * O(V * E) time; space is O(V^2) because per-source state is kept on every
+ * vertex, so this suits small / medium graphs.
+ */
+@Description(name = "betweenness_centrality", description = "built-in udga for BetweennessCentrality")
+public class BetweennessCentrality implements AlgorithmUserFunction