diff --git a/postgraphile/postgraphile/__tests__/kitchen-sink-schema.sql b/postgraphile/postgraphile/__tests__/kitchen-sink-schema.sql
index 23f66951c3..836e91f426 100644
--- a/postgraphile/postgraphile/__tests__/kitchen-sink-schema.sql
+++ b/postgraphile/postgraphile/__tests__/kitchen-sink-schema.sql
@@ -259,6 +259,7 @@ create table c.edge_case (
alter table c.edge_case drop column drop_me;
create function c.edge_case_computed(edge_case c.edge_case) returns text as $$ select 'hello world'::text $$ language sql stable;
+comment on function c.edge_case_computed is E'@sortable';
create domain a.an_int as integer;
create domain b.another_int as a.an_int;
diff --git a/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.json5 b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.json5
new file mode 100644
index 0000000000..c12c4bfc9c
--- /dev/null
+++ b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.json5
@@ -0,0 +1,26 @@
+{
+ allEdgeCases: {
+ nodes: [
+ {
+ computed: "hello world",
+ wontCastEasy: 20,
+ rowId: 1,
+ },
+ {
+ computed: "hello world",
+ wontCastEasy: null,
+ rowId: 2,
+ },
+ {
+ computed: "hello world",
+ wontCastEasy: -512,
+ rowId: 3,
+ },
+ {
+ computed: "hello world",
+ wontCastEasy: null,
+ rowId: 4,
+ },
+ ],
+ },
+}
diff --git a/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.mermaid b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.mermaid
new file mode 100644
index 0000000000..1e4c33a14f
--- /dev/null
+++ b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.mermaid
@@ -0,0 +1,54 @@
+%%{init: {'themeVariables': { 'fontSize': '12px'}}}%%
+graph TD
+ classDef path fill:#eee,stroke:#000,color:#000
+ classDef plan fill:#fff,stroke-width:1px,color:#000
+ classDef itemplan fill:#fff,stroke-width:2px,color:#000
+ classDef unbatchedplan fill:#dff,stroke-width:1px,color:#000
+ classDef sideeffectplan fill:#fcc,stroke-width:2px,color:#000
+ classDef bucket fill:#f6f6f6,color:#000,stroke-width:2px,text-align:left
+
+
+ %% plan dependencies
+ Object11{{"Object[11∈0] ➊
ᐸ{pgSettings,withPgClient}ᐳ"}}:::plan
+ Access9{{"Access[9∈0] ➊
ᐸ2.pgSettingsᐳ"}}:::plan
+ Access10{{"Access[10∈0] ➊
ᐸ2.withPgClientᐳ"}}:::plan
+ Access9 & Access10 --> Object11
+ __Value2["__Value[2∈0] ➊
ᐸcontextᐳ"]:::plan
+ __Value2 --> Access9
+ __Value2 --> Access10
+ __Value4["__Value[4∈0] ➊
ᐸrootValueᐳ"]:::plan
+ Connection12{{"Connection[12∈0] ➊
ᐸ8ᐳ"}}:::plan
+ PgSelect14[["PgSelect[14∈1] ➊
ᐸedge_caseᐳ"]]:::plan
+ Object11 & Connection12 --> PgSelect14
+ PgSelectRows15[["PgSelectRows[15∈1] ➊"]]:::plan
+ PgSelect14 --> PgSelectRows15
+ __Item16[/"__Item[16∈2]
ᐸ15ᐳ"\]:::itemplan
+ PgSelectRows15 ==> __Item16
+ PgSelectSingle17{{"PgSelectSingle[17∈2]
ᐸedge_caseᐳ"}}:::plan
+ __Item16 --> PgSelectSingle17
+ PgClassExpression19{{"PgClassExpression[19∈3]
ᐸ”c”.”edge_...ge_case__)ᐳ"}}:::plan
+ PgSelectSingle17 --> PgClassExpression19
+ PgClassExpression20{{"PgClassExpression[20∈3]
ᐸ__edge_cas...cast_easy”ᐳ"}}:::plan
+ PgSelectSingle17 --> PgClassExpression20
+ PgClassExpression21{{"PgClassExpression[21∈3]
ᐸ__edge_case__.”row_id”ᐳ"}}:::plan
+ PgSelectSingle17 --> PgClassExpression21
+
+ %% define steps
+
+ subgraph "Buckets for queries/v4/orderby-computed"
+ Bucket0("Bucket 0 (root)"):::bucket
+ classDef bucket0 stroke:#696969
+ class Bucket0,__Value2,__Value4,Access9,Access10,Object11,Connection12 bucket0
+ Bucket1("Bucket 1 (nullableBoundary)
Deps: 11, 12
ROOT Connectionᐸ8ᐳ[12]
1: PgSelect[14]
2: PgSelectRows[15]"):::bucket
+ classDef bucket1 stroke:#00bfff
+ class Bucket1,PgSelect14,PgSelectRows15 bucket1
+ Bucket2("Bucket 2 (listItem)
ROOT __Item{2}ᐸ15ᐳ[16]"):::bucket
+ classDef bucket2 stroke:#7f007f
+ class Bucket2,__Item16,PgSelectSingle17 bucket2
+ Bucket3("Bucket 3 (nullableBoundary)
Deps: 17
ROOT PgSelectSingle{2}ᐸedge_caseᐳ[17]"):::bucket
+ classDef bucket3 stroke:#ffa500
+ class Bucket3,PgClassExpression19,PgClassExpression20,PgClassExpression21 bucket3
+ Bucket0 --> Bucket1
+ Bucket1 --> Bucket2
+ Bucket2 --> Bucket3
+ end
diff --git a/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.sql b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.sql
new file mode 100644
index 0000000000..d1b70920b5
--- /dev/null
+++ b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.sql
@@ -0,0 +1,7 @@
+select
+ "c"."edge_case_computed"(__edge_case__) as "0",
+ __edge_case__."wont_cast_easy"::text as "1",
+ __edge_case__."row_id"::text as "2",
+ __edge_case__."not_null_has_default"::text as "3"
+from "c"."edge_case" as __edge_case__
+order by "c"."edge_case_computed"(__edge_case__) asc;
\ No newline at end of file
diff --git a/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.test.graphql b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.test.graphql
new file mode 100644
index 0000000000..1cbd72c852
--- /dev/null
+++ b/postgraphile/postgraphile/__tests__/queries/v4/orderby-computed.test.graphql
@@ -0,0 +1,11 @@
+## expect(errors).toBeFalsy();
+#> schema: ["a", "b", "c"]
+{
+ allEdgeCases(orderBy: COMPUTED_ASC) {
+ nodes {
+ computed
+ wontCastEasy
+ rowId
+ }
+ }
+}
\ No newline at end of file