Every tool ships someone else's factory

Scheduling software arrives with opinions about what you make and how. Ours did too — three resource types, decided before we met you, with a rename button to paper over the gap. This is what we learned from watching people work around our own defaults, and why we deleted them.

Open almost any scheduling or planning tool and you will find, somewhere near the bottom of the settings, the shape of a factory you have never visited. Rooms. Assets. Equipment. Work centres. Whatever the words, they were chosen by someone who had a particular operation in mind, and if yours is that operation the software feels like it was written for you. If it is not, you spend the first week translating.

We know, because we did it. Orkyo shipped with three resource types — Spaces, People and Tools — and a rename button. Call a Space a Workstation, we said. Call it a Cell, or a Machine. The words are yours.

That was a real answer to a real problem, and it was not good enough. This is why.

A rename is not a model

Here is the thing about renaming a Space to a Machine: everything else still thinks it is a Space.

The page is built for spaces. The empty state says something about spaces. The import dialog explains what a space is. The product tour walks you through spaces. The quota counts spaces. Search indexes them as spaces. When something goes wrong, the error message mentions a space, and now you are the person who has to remember that when the software says space it means the Mazak in bay three.

Worse, one word had to cover everything that stands still. A machining cell and the mill inside it are not the same kind of thing, but if you only have one located type you have to pick which one gets to exist. Most shops picked the area, because that is what draws nicely on a floorplan, and then had no place to record spindle speed, tool changer positions, or when the thing was last calibrated. The machine — the actual expensive constrained resource the whole schedule turns on — lived in the description field, or in a spreadsheet beside the one you were supposed to be replacing.

We had written a scheduling tool for machine shops in which you could not schedule a machine. You could schedule the floor tile it stood on.

The argument we made to ourselves

There is a defensible reason to ship built-in types, and we made it for a long time.

An empty product is a cruel product. A new workspace with no resource types is a blank form asking you to invent an ontology before you can book anything. Defaults are a kindness: they get someone to a scheduled job on the first afternoon rather than the second week. Every product person knows the graveyard of tools that were infinitely configurable and therefore unusable.

The trouble is that this argument justifies starting points, and we had built foundations. Spaces and People were not defaults you could move past. They were load-bearing. The pages depended on them, so they could not be removed. Their behaviour could not be changed, because the pages assumed it. We had a dialog that greyed out its own checkboxes and explained, more or less, that this part of your factory was not up to you.

A default you cannot leave is not a default. It is a decision, taken on your behalf, by people who have not seen your shop floor.

What people did instead

You can see the workaround in the data model if you know where to look.

Somebody needed a maintenance log per machine, and there was nowhere to put it, so it became a description field with dates typed into it. Somebody needed a department hierarchy, and we had one — right up until we moved departments into a general-purpose list and flattened the tree, because the general mechanism could not express a parent. So the parent became a name typed into a text box, matching nothing, checked by nothing. We shipped that. It was in the migration notes as a known cost, which is a polite way of saying we broke something and wrote it down.

Somebody registered forty machines by importing a spreadsheet, then wanted them on the floorplan, and found that drawing a shape only ever created a new resource. The way to get an existing machine onto the plan was to draw a duplicate and delete the original — losing whatever the original carried.

None of these are exotic. They are the ordinary things a shop needs on an ordinary Tuesday. Each one had a workaround, and every workaround was a small tax on someone who had already paid us to remove one.

Deleting our own defaults

So we took the built-in types out. Not deprecated, not hidden behind a flag: removed, along with the pages that assumed them.

What replaced them is a catalog. Mills, lathes, drills, CNC machines, assembly stations, test stations, benches, people, tools, forklifts — each one arriving with the fields that kind of thing usually carries, because a mill you have to describe from an empty form is barely better than no mill at all. You switch on the ones you have. If your operation schedules something the catalog has never heard of, you define it, and it is not a second-class type, because there is no first class for it to be excluded from.

The kindness argument survives, in other words. The starting point is still there. It just stopped being a floor you cannot dig through.

Two things fell out of that decision that we did not fully anticipate.

The first is that the navigation got smaller. When every type had its own page, the sidebar grew with your ambition — twelve machine types meant twelve entries, and the product punished you for modelling your shop accurately. Now there are two entries, Stations and Assets, split by the one distinction that actually changes behaviour: whether the thing stays put. Adding a type costs no navigation at all.

The second is that “reference data” turned out to be one problem, not four. Departments, job titles, a maintenance log, a parts catalog — we had been solving these one at a time, each with its own table and its own page. They are all lists with typed columns. Once that was a single mechanism, the department tree came back for free, as a column that references another row in the same list, with the cycle check the old foreign key used to provide.

What this costs you

Honesty about the trade: this release asks a new workspace a question it did not ask before. Before you can schedule anything, you have to say what you schedule.

We think that question is the right one, and that being asked it on day one is better than discovering on day forty that the answer was decided for you. But it is a real step, and we have tried to make it a short one — the catalog is there so that the answer is usually a few switches rather than a modelling exercise.

The deeper cost is ours, and we accepted it deliberately: we removed tables from a database that customers self-host, which means Community operators cannot roll back past this release. We do not do that lightly, and we do not expect to do it often. It was the price of not carrying our own bad defaults forever.

The general lesson, if there is one

Software encodes assumptions whether or not anyone decides to. The question is only whether the assumptions are visible and removable.

Ours were neither. They were three words in a sidebar that looked like an obvious way to organise a product, and it took watching people rename things to notice that the words were doing more work than they had any right to.

If you evaluate a scheduling tool, it is worth asking what it thinks you make — and then asking what happens when you tell it that it is wrong.

Read what shipped in Nothing is built in any more, or start with the type catalog.