I Built a Journey Entity and Then Scrapped It
I built a new entity called Journey to bundle scattered items, got 80% of the way, then threw it out. The realization: an entity's boundary is invisible in isolation — it surfaces only when you try to connect it to other things.
I Built a Journey Entity and Then Scrapped It
Starting from the intuition: “we need an integration layer”
Something had been nagging me — Fecit’s scattered features (templates, routines, reviews) only get tied together inside the user’s head, never at the system level. If the system itself recognized the bundle, it’d help with the longer game of actually achieving things. So I decided to build a new entity that groups items into one goal-unit.
The name was Goal at first, but “Goal” carries too much pressure / constraint feel, so we landed on Journey (여정).
Stages 1 and 2 went cleanly
I built Journey model + CRUD endpoints on the server, plus a mobile entry point in the Achiever tab, with list / create / edit / menu screens. I followed the existing Project pattern, so the code style stayed consistent, and it worked.
Two commits in. At this point I believed we were on track.
A crack appeared while designing stage 3
Stage 3 was “link Task / Project / Reservation to Journey.” Felt simple — just add a journey_id foreign key on each model.
Here’s where the first crack hit.
Journey is personal. Project and Task are shared. Linking via
journey_idis wrong.
Right. Stamping a personal-context field onto a shared entity poisons the data model. Two members of the same Project might want to bind it to different journeys (one to “diet,” another to “health management”) — a single column can’t hold that.
So I pivoted to a junction collection: journey_links with (journey_id, linked_id, linked_type, created_by) — many-to-many, owned by the user, doesn’t dirty the shared entity. Looked clean.
Then the deeper crack:
The more we build, the blurrier the line between Journey and Project gets.
I had to be honest. Yes — what we’re building, “a Journey container that holds items,” is essentially a Project with zero members.
What was the difference, actually?
- Project = team / collaboration goal, shared with members
- Journey = personal goal, just me
The distinction was a single axis: “shared or not.” Functionally:
- Both have title, description, deadline
- Both group tasks
- Both render an inside-view of “what’s contained”
Real differentiation should be about meaning — where they behave differently — but I hadn’t expressed that in code. I was just shaping them the same on the surface and calling them different.
You can’t see it before you try to build it
The funny part: the overlap was invisible until I started designing the connections.
Looking at the entities in isolation, Journey and Project felt different. Different names, different intent. But the moment I started designing “how does this connect to other things?” — that’s when it became obvious that they were the same shape of bowl.
The boundary of an entity isn’t visible by itself. It surfaces only when you try to connect it. An entity defined in isolation looks clean, but the moment you start carving the surfaces where it touches other entities, its real shape appears.
So I built 80% and threw it away
Server + mobile UI + i18n + atom + 4 screens + 2 components = two commits. Built and verified working. Then scrapped.
Looks inefficient, but as I wrote in The Value of Abandoned Attempts — what an abandoned attempt leaves behind is a record of dislike. What this attempt left me is one sentence.
Before creating a new entity, work out where its boundary actually differs from the existing entities. The boundary is invisible in isolation and only surfaces at connection time, so try to draw the connection scenarios first.
That sentence will fire faster in the next decision.
What’s next
The direction flipped from “let’s not make Journey” to “let’s make Project better.” So that it works naturally even with zero members. So that it can include personal routines (Reservation). So that it can carry progress, review, milestones. Maybe what I was trying to put into Journey actually belonged in Project all along.
Today I didn’t ship a single line of net new code. But one thing got clearer. That alone makes the day worth it.