diff --git a/Project.toml b/Project.toml
index 07da5491f..fdb0ead33 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,10 +1,11 @@
 name = "Compat"
 uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
-version = "4.10.1"
+version = "4.11.0"
 
 [deps]
 Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
 LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
+TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
 UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
 
 [compat]
diff --git a/README.md b/README.md
index 42566cbe3..17ce22b9d 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,8 @@ changes in `julia`.
 
 * `@something` and `@coalesce` as short-circuiting versions of `something` and `coalesce` ([#40729]) (since Compat 3.29)
 
+* `pkgversion(m::Module)` returns the version of the package that loaded a given module ([#45607]) (since Compat 4.11)
+
 ## Developer tips
 
 One of the most important rules for `Compat.jl` is to avoid breaking user code
@@ -170,5 +172,7 @@ Note that you should specify the correct minimum version for `Compat` in the
 [#43334]: https://github.com/JuliaLang/julia/issues/43334
 [#43354]: https://github.com/JuliaLang/julia/issues/43354
 [#43852]: https://github.com/JuliaLang/julia/issues/43852
+[#45607]: https://github.com/JuliaLang/julia/issues/45607
+[#46104]: https://github.com/JuliaLang/julia/issues/46104
 [#48038]: https://github.com/JuliaLang/julia/issues/48038
 [#50105]: https://github.com/JuliaLang/julia/issues/50105
diff --git a/src/Compat.jl b/src/Compat.jl
index 83e327dfd..751355a1f 100644
--- a/src/Compat.jl
+++ b/src/Compat.jl
@@ -385,6 +385,71 @@ end
     end
 end
 
+# this function is available as of Julia 1.9
+# https://github.com/JuliaLang/julia/pull/45607
+# https://github.com/JuliaLang/julia/pull/45695
+# https://github.com/JuliaLang/julia/pull/45861
+# https://github.com/JuliaLang/julia/pull/46738
+@static if !isdefined(Base, :pkgversion)
+    using TOML: parsefile
+    export pkgversion
+
+    const require_lock = isdefined(Base, :require_lock) ? Base.require_lock : Base.ReentrantLock()
+    const project_names = ("JuliaProject.toml", "Project.toml")
+
+    function locate_project_file(env::String)
+        for proj in project_names
+            project_file = joinpath(env, proj)
+            if Base.isfile_casesensitive(project_file)
+                return project_file
+            end
+        end
+        return nothing
+    end
+
+    function get_pkgversion_from_path(path)
+        project_file = locate_project_file(path)
+        if project_file isa String
+            d = parsefile(project_file)
+            v = get(d, "version", nothing)
+            if v !== nothing
+                return VersionNumber(v::String)
+            end
+        end
+        return nothing
+    end
+
+    """
+        pkgversion(m::Module)
+
+    Return the version of the package that imported module `m`,
+    or `nothing` if `m` was not imported from a package, or imported
+    from a package without a version field set.
+
+    The version is read from the package's Project.toml during package
+    load.
+
+    To get the version of the package that imported the current module
+    the form `pkgversion(@__MODULE__)` can be used.
+    """
+    function pkgversion(m::Module)
+        path = pkgdir(m)
+        path === nothing && return nothing
+        Base.@lock require_lock begin
+            v = get_pkgversion_from_path(path)
+            # https://github.com/JuliaLang/julia/pull/44318
+            @static if hasfield(Base.PkgOrigin, :version)
+                pkgorigin = get(Base.pkgorigins, Base.PkgId(Base.moduleroot(m)), nothing)
+                # Cache the version
+                if pkgorigin !== nothing && pkgorigin.version === nothing
+                    pkgorigin.version = v
+                end
+            end
+            return v
+        end
+    end
+end
+
 # https://github.com/JuliaLang/julia/pull/43334
 if VERSION < v"1.9.0-DEV.1163"
     import Base: IteratorSize, HasLength, HasShape, OneTo
diff --git a/test/runtests.jl b/test/runtests.jl
index 04c110616..2268b610c 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -1,5 +1,6 @@
 using Compat
 using Dates
+using TOML
 using Test
 
 @test isempty(detect_ambiguities(Base, Core, Compat))
@@ -457,6 +458,12 @@ end
     @test isempty(ea)
 end
 
+@testset "pkgversion" begin
+    toml = joinpath(pkgdir(Compat), "Project.toml")
+    @test pkgversion(Compat) == VersionNumber(TOML.parsefile(toml)["version"])
+    @test pkgversion(Base) === nothing
+end
+
 # https://github.com/JuliaLang/julia/pull/43334
 @testset "stack" begin
     # Basics