BLOG

Making time: Galactus DB 1.7.1

18/10/2026

Published

Most organisations have a scheduling problem somewhere. Care visits have to fit around staff hours and the drive between clients. An operation needs a surgeon, an anaesthetist and a theatre at the same time. Exams need rooms with enough seats, and a paint line loses an hour every time it changes colour. The answer usually lives in a spreadsheet, or in a separate optimiser that the data has to be exported to.

Galactus DB 1.7.0 added a scheduler to the database. 1.7.1 lets you see its plans as a chart and build the call from a form, in Explorer and in Station. We didn't write a post for 1.7.0, so this one covers both releases.

Why schedule in a graph

The hard part of most schedules is the relationships between things, and those are what a graph stores.

Take who can do what. A nurse can take a visit if they hold every qualification it needs, and an engineer can take a job if they are trained on that model of boiler. Qualifications and training are relationships, so the check is a pattern match.

Clashes work the same way. Two exams can't run at the same time if any student sits both. Two fixtures clash if they share a team, and two talks clash if they share a speaker. The scheduler works the clashes out from who is linked to what, so nobody has to list them.

History matters too. A client who has seen the same carer for a year should keep seeing them, and the past visits are already in the graph for the scheduler to prefer. Order is often stored as well: prep before surgery, heats before finals, the delivery before the fitting. One MATCH turns those relationships into rules. Clients, sites and depots are nodes with locations, so travel time is part of the plan from the start.

A separate scheduling tool needs all of this exported into its own format, and the export has to be repeated whenever someone gains a skill or changes a booking. A scheduler inside the database reads the current graph every time it runs.

1.7.0: the Native Scheduler

gdb.schedule.solve takes the tasks and resources you match and reads everything else through Cypher expressions over your own labels and properties. There's no scheduling schema to adopt. Here is a morning of home care visits. Some visits need two people, regular clients get staff who have visited them before, and nobody works more than three hours without a 30-minute break:

MATCH (v:Visit) WHERE v.duration IS NOT NULL WITH collect(v) AS visits
MATCH (s:Staff) WITH visits, collect(s) AS staff
CALL gdb.schedule.solve({
  tasks: visits, resources: staff, randomSeed: 1,
  task: {required: 'coalesce(t.people, 1)'},
  pair: {affinity: 'size([(r)-[:VISITED]->(:Visit)-[:FOR]->(c)<-[:FOR]-(t) | 1])'},
  constraints: [{type: 'maxContinuous', amount: 180, breakLength: 30}]
})
YIELD task, resources, start, end
UNWIND resources AS person
CREATE (person)-[:BOOKED {start: start, end: end}]->(task)
RETURN task.name, person.name, start ORDER BY start;

Each placement comes back as a row with the task, the people it uses and its start and end. Here the plan goes straight back into the graph as BOOKED relationships, where you can query it like any other data. The home care recipe has the data to try it with.

The same call covers very different problems:

On Galactus DB 1.7.0 (Intel Core i9-13900K, 64 GB RAM), a day of 2,000 tasks on 100 resources solves in about 2.5 seconds, with travel, 80 tasks that need two people and a break rule. Search and performance covers the time budget and how to get repeatable plans.

The scheduling recipes are eleven complete examples you can paste into an empty database, among them a hospital theatre list, an exam timetable, sports fixtures, a factory floor and re-planning after a change. The Native Scheduler demo runs six of them in your browser so you can watch the search improve the plan. The scheduling guide has every option.

1.7.0 also added vector.normalize, which scales a list such as a FastRP embedding to unit length, and vector.norm.euclidean, which measures it. See vector norm and normalisation, or the graph embeddings demo for FastRP at work.

1.7.1: see the plan, then build the call

A list of rows is hard to check by eye. In 1.7.1, when you run gdb.schedule.solve.stats in Explorer, the result opens as a Gantt chart. This one is an afternoon of a dance competition, with three stages and dancers who need 15 minutes between dances:

A dance afternoon planned by gdb.schedule.solve

Each stage, carer, theatre or machine gets a lane. Time outside its working hours is shaded, and the share of its time that is booked sits next to its name. You can switch the lanes to participants to see each person's day. Clicking a task highlights every lane it uses, and tasks that couldn't be placed are listed with the reason, such as RuleLimit:maxTasks. The chart also works for any query that returns a start and an end per row, so bookings you wrote back last week chart the same way. The Schedule view guide lists the controls.

The ▤ Schedule button in Explorer opens a builder. You pick the task and resource labels, durations, availability, who can take what, rules and the order of priorities, and the Cypher is written as you go. Labels, relationship types and property names are suggested from your database. You can insert the call into the editor and change it by hand, or run it straight away. See the schedule builder guide.

1.7.1 also gives a clearer error when an expression uses the wrong name. Scheduler expressions refer to the task as t and the resource as r. In 1.7.0, task.minutes quietly evaluated to null and the error was about a missing duration. 1.7.1 names the mistake:

expression `task.minutes` uses `task`, which is not defined here; it can use `t`

In Galactus DB Station

Galactus DB Station 0.3.1 has the same Schedule view and builder, and its built-in database runs 1.7.1, so you can try the scheduler on a laptop with nothing else installed. Station's builder writes the same Cypher as Explorer's, and a test keeps them in step. The Station guide covers the result views.

Upgrading

Pull and restart:

docker pull ianknowles/galactus-db:1.7.1
docker pull ianknowles/galactus-db-explorer:1.7.1

The data, commit log, snapshot and dump formats haven't changed since 1.6.1, so 1.6 and 1.7 releases open each other's databases and there's nothing to migrate.

What's next

Next, the scheduler will take travel times from the road network already stored in your graph, so a visit across the river costs the drive over the bridge rather than the straight-line distance.