How I’d approach it
Four requests I hear often, and the answer I’d give to each. They come from systems I’ve built, taken over and run myself — but the real answer changes once I hear the actual situation.
-
Internal tools
“We want one system the whole company — about 100 people — uses to manage projects.”
-
01
What I’d ask first
- Who types the numbers in, and who only reads them? The people who enter and the people who look need different screens.
- Which figure does management actually decide on — revenue, cost or utilisation? That screen gets built first.
- Where does the data live today — spreadsheets, Trello, chat? I’d pull it from there rather than make people type it twice.
- Do people go back to old records often? That decides whether you need search or a list is enough.
-
02
How I’d split it
- Three separate things: the records, the calculation rules, and the history.
- Calculation rules — cost, utilisation, targets — live in one place, as data rather than code. They change every quarter.
- History is append-only. Never update a row, add one — then “who changed what, when” comes for free.
- Permissions attach to the state of a record, not to a screen.
-
03
What I’d build it with
- Laravel or Node.js, with Vue.js. Internal tools grow screens fast, so I want to stamp out forms and lists quickly.
- MySQL, with the aggregation written as plain SQL the next person can read.
- Notifications go where people already are — Slack or Lark — not into yet another inbox.
- One server is enough for 100 people. I wouldn’t split anything up front.
-
04
Where this usually breaks
- An integration was registered under one person’s account. When they leave, it quietly stops.
- “Just hard-code it for this quarter.” Six months later nobody knows which numbers are hard-coded.
- Someone will ask for a CSV export. Bolt it on late and the data model gets reworked.
-
-
Servers & operations
“One person looks after our server by hand. We want it safer, and not dependent on them.”
-
01
What I’d ask first
- How do you deploy today, and how do you undo a bad deploy?
- Who can log in to the server, and how? Shared passwords and open SSH are where I look first.
- Where do the API keys and database passwords live right now?
- How do you find out the server is down — an alert, or a customer?
-
02
How I’d split it
- Build the way back first. Rolling back in seconds matters more than deploying faster.
- Close the doors before adding features: one port open, no direct SSH, access only through a managed path.
- Decide where secrets live on day one — a secret store or the environment, never the repository.
- Anything done by hand once a year, like certificate renewal, gets automated. Someone will forget it.
-
03
What I’d build it with
- On a VPS: git-based deploys, cron for backups, and Let’s Encrypt with automatic renewal.
- On AWS: SSM instead of SSH, Secrets Manager for keys, CloudWatch alarms for memory, downtime and 5XX spikes.
- For a small service: Cloud Run deploying automatically from main, so rollback is picking the previous revision.
- Start on the smallest server that works and scale when the alarms say so. Terraform once the setup no longer fits in one person’s head.
-
04
Where this usually breaks
- Even after automation, someone SSHes in when it’s urgent. That’s the moment the docs and the server diverge.
- A token gets written straight into the code “just for now” — and stays in the git history for good.
- The yearly certificate renewal lives in one person’s head. The year they’re on holiday, the site goes down.
-
-
Taking over a system
“The person who built our system has left. We need someone to take it over.”
-
01
What I’d ask first
- Does someone use it every day? If so, nothing gets rewritten — it gets understood first.
- Is there any documentation, even old? I read it, then check it against the code. They rarely agree.
- Which outside services is it connected to, and under whose accounts?
- What runs on a schedule — cron, batch jobs, month-end scripts? Those are what get forgotten.
-
02
How I’d split it
- Read before changing. Put logs where things fail and let them show the cause.
- Reproduce current behaviour exactly before improving it. Odd behaviour gets a note, not a silent fix.
- Pull tangled side tools out one at a time, each into something small enough to undo.
- Write the handover document as I go, so the next person doesn’t start from zero the way I did.
-
03
What I’d build it with
- Temporary trace logs at each step of a failing flow, removed once the cause is found.
- New pieces default to safe: dry-run instead of writing, and every request refused until a key is set.
- The old code stays next to the new until the new one has run a full cycle — a month-end, a payday.
- A handover doc that opens with the five facts to read first, and how to roll back in under a minute.
-
04
Where this usually breaks
- Integrations tied to the departed person’s account stop working weeks later, where nobody is looking.
- A feature nobody documented always turns up. Usually a screen one person uses at month-end.
- “While we’re in there anyway…” Mixing takeover with improvement makes both of them late.
-
-
External integrations
“We want to connect LINE, Rakuten, Lark and e-contracts, so nobody copies data by hand.”
-
01
What I’d ask first
- When the two sides disagree, which one holds the truth?
- What should happen when the other service doesn’t answer — wait, retry, or tell someone?
- Whose credentials will it run on? Is it for one company, or many?
- Are there limits on the other side — call limits, plan restrictions, fields you simply can’t get?
-
02
How I’d split it
- Never trust what the user types. Check it against the source API before linking anything.
- Every sync is safe to run twice: clear and re-insert per period, rather than “add whatever’s new.”
- Every failure gets its own code and a log line, so a support question can be answered in minutes.
- Each customer’s keys are encrypted at rest, and which customer a request belongs to is decided by the login — never by what the request claims.
-
03
What I’d build it with
- Laravel or Node.js, with a scheduler for anything periodic.
- Webhooks verified by signature, with a nonce so the same request can’t be replayed.
- Timeouts and retries on every outbound call, sent in batches small enough for the other side’s limits.
- An alert to Slack or Lark when the retries run out, so a human hears about it.
-
04
Where this usually breaks
- The other side changes its plan or shuts a feature down, and the integration breaks without a single deploy.
- The same webhook arrives twice. Without a duplicate check, you act on it twice.
- Someone discovers that just saying “I’m company A” is enough to get company A’s data.
-
Most of what’s under “where this usually breaks” is something I’ve run into myself. Tell me the actual situation and the answer will look different — usually simpler.