Healthcheck for Fractional CTO

This is the framework behind a healthcheck I have used in advisory and fractional CTO work. Founders can also use it internally to review engineering risk.
The goal is not to prove that the team is bad. The goal is to find where the product is fragile before reality finds it for you.
Most startup engineering problems do not look dramatic at first. The code works on one laptop. Deploys usually succeed. The founder gets screenshots in Slack. The team says they can move fast. In a composite example, a customer reports a bug, nobody can reproduce it, the production logs are useless, the payment flow has no test coverage, the only senior engineer is on vacation, and everyone discovers that "moving fast" was actually "remembering many undocumented things."
A good healthcheck turns that vague anxiety into a map.
It should answer four questions:
- What risks can hurt the company?
- What evidence do we have that those risks are controlled?
- Which controls are too heavy for the current stage?
- What should change first?
This is an updated version of my older startup development checklist. I still care about clean code, conventions, CI/CD, documentation, observability, and planning. But I no longer believe startup teams should copy universal rules blindly. A pre-seed prototype, regulated fintech product, internal AI tool, and marketplace with live payments should not be judged by the same process dogma.
The durable part is not a specific ceremony. The durable part is intent, tests, observability, reproducibility, and risk control.
How to run the workshop
Book two hours with the people who actually build and operate the product.
For a small team, that usually means founders, technical lead, product owner, designer if the product surface is important, and the engineers who understand the critical flows. My older version said to keep business stakeholders out. I would soften that now. Keep the meeting small, but include anyone whose decisions affect engineering reality.
Use a 1 to 5 score for each area:
- Absent: no reliable practice, mostly hope.
- Ad hoc: works only because someone remembers.
- Functional: good enough for the current stage, with known gaps.
- Strong: repeatable, documented, and visible.
- Leverage: improves speed and quality without adding much drag.
For every score below 3, write one action. For every score of 5, ask whether the team is over-investing for its stage. A perfect enterprise process can be a startup disease too.
End with a ranked action plan. Do not leave with fifty improvements. Leave with the top five risks, the owner for each, and the evidence that will prove the fix.
1. Product intent
Bad engineering often starts before code.
Score the team on whether builders understand the product intent behind their work:
- Can an engineer explain the user, pain, and business reason for the current feature?
- Are acceptance criteria written as behavior, not vague tasks?
- Do tickets include non-functional constraints such as privacy, performance, availability, compliance, and cost where they matter?
- Is there a visible decision record for major product and architecture choices?
- Does the team know what not to build?
In an AI-assisted engineering world, this matters more, not less. If implementation gets cheaper, vague intent becomes the bottleneck. Agents can generate code quickly. They cannot rescue a team that has not decided what "correct" means.
Good signal: a new engineer or coding agent can read the issue and produce a reasonable plan without a private explanation from the founder.
Bad signal: every task requires a meeting because the written description hides the actual decision.
2. Code clarity
Clean code is not about aesthetic purity. It is about whether the next change can be made without fear.
Score the codebase on:
- Naming consistency.
- Function and module size.
- Local simplicity.
- Type usage.
- Dependency boundaries.
- Duplicate logic.
- Whether important business concepts are explicit.
I still like the old principles: keep it simple, leave the code better than you found it, use descriptive names, avoid magic numbers, reduce needless repetition, and do not comment obvious noise.
But I would remove the universal dogma. Polymorphism is not always better than an if. Static functions are not automatically bad. One-week sprints are not automatically good. The question is always: what risk is this practice controlling?
Use abstraction when it removes real complexity or protects a meaningful boundary. Avoid abstraction when it hides the thing everyone needs to understand.
Good signal: a developer can change a common workflow without touching five unrelated concepts.
Bad signal: simple product changes require archeology.
3. Tests as product proof
Testing is not a badge. It is executable evidence.
Score the team on:
- Unit tests for important logic.
- Integration tests for critical service boundaries.
- End-to-end tests for core user journeys.
- Regression tests for past serious bugs.
- Test data that is realistic enough to catch problems.
- The ability to run tests locally and in CI.
- Whether failed tests are treated as product signals, not chores.
I do not care about 100 percent line coverage as a trophy. I care whether the dangerous behavior is covered.
For a startup, the critical paths usually include signup, payment, onboarding, data import, permission checks, notifications, analytics events, admin actions, and whatever workflow creates the product's promise.
If a team says "we move too fast for tests," I translate that as "we are borrowing from the future without tracking the debt." Sometimes that loan is rational. It should still be explicit.
Good signal: before a release, the team can show which automated checks protect the business-critical flows.
Bad signal: the founder tests production manually after every deploy because nobody trusts the system.
4. Reproducible environments
A product that works only on one machine is not a product. It is a local ritual.
Score the team on:
- Local setup time.
- Dependency management.
- Environment variable documentation.
- Seed data.
- Containerization or equivalent reproducibility.
- Staging environment quality.
- Whether production-like behavior can be tested safely.
I still like Docker and Docker Compose for many startup teams, but the specific tool matters less than the outcome. A new developer or agent should be able to get a working environment quickly, without collecting secrets from Slack history.
Configuration should be separate from code. The Twelve-Factor App remains a useful reference for config discipline, even if not every startup needs to follow every twelve-factor rule literally.
Good signal: onboarding a new engineer exposes product complexity, not setup folklore.
Bad signal: "Ask Alex, he knows how to run it."
5. Delivery and deployment
The old version of this checklist said never deploy directly to production. I would say it differently now.
Do not deploy changes whose risk you cannot see, test, or reverse.
Some teams can safely ship small changes directly behind feature flags with strong tests, observability, review, and rollback. Other teams need staging because production is risky, data-heavy, regulated, or operationally fragile.
Score delivery on:
- CI checks for every meaningful change.
- Code review proportionate to risk.
- Deployment automation.
- Rollback or forward-fix strategy.
- Feature flags for uncertain behavior.
- Release notes or internal change visibility.
- Clear ownership when a deployment fails.
The current DORA software delivery metrics are useful here because they focus on outcomes across five measures: change lead time, deployment frequency, failed deployment recovery time, change fail rate, and deployment rework rate. If you know the older four-key model, treat it as historical shorthand, not the current complete model. Do not worship the metrics. Use them to ask better questions.
Good signal: the team can explain how a change reaches users and how it gets reversed.
Bad signal: deployment is a ceremony everyone fears.
6. Observability
If something breaks and the team cannot see it, the customer becomes your monitoring system.
Score observability on:
- Structured logs.
- Error tracking.
- Metrics for important services.
- Tracing for complex flows.
- Product analytics for core behavior.
- Alerting tied to user impact.
- Dashboards that someone actually uses.
OpenTelemetry is a strong standard reference for modern telemetry. Tools will change. The principle will not: production should explain itself.
Frontend observability matters too. If users cannot complete onboarding or payment, backend uptime is not enough. Watch the real journey, not only server health.
Good signal: when a user reports a bug, the team can reconstruct what happened.
Bad signal: logs exist, but nobody can find the event that matters.
7. Security and data boundaries
Security health is not only penetration testing. It is everyday discipline.
Score the team on:
- Secrets outside the repository.
- Least-privilege access.
- Authentication and authorization tests.
- Dependency vulnerability handling.
- Auditability of sensitive admin actions.
- Data retention and deletion rules.
- Incident response basics.
For web products, the OWASP Application Security Verification Standard is a useful reference. A tiny startup does not need enterprise theater, but it does need to know where sensitive data lives and who can touch it.
AI features make this more important. If you send customer data to model providers, enrichment APIs, transcription tools, or analytics platforms, the data boundary must be explicit. "It is just a prototype" is not a privacy policy.
Good signal: the team can describe the sensitive data lifecycle in plain language.
Bad signal: production credentials live in chats, screenshots, or old onboarding docs.
8. API and integration contracts
Startups break themselves through hidden contracts.
Score the team on:
- API documentation.
- Request and response examples.
- Error shape consistency.
- Versioning strategy where needed.
- Webhook retry behavior.
- Third-party dependency mapping.
- Ownership of integration failures.
OpenAPI is useful when the backend serves external or internal clients. The point is not a pretty Swagger page. The point is that humans and machines can understand the contract.
If a frontend, mobile app, backend, agent, partner integration, and analytics system all rely on the same behavior, undocumented assumptions become bugs.
Good signal: a client developer can integrate without guessing.
Bad signal: the API contract is "look at how the current frontend calls it."
9. Team operating rhythm
Daily standups are not mandatory. One-week sprints are not mandatory. Scrum is not mandatory. Kanban is not mandatory.
A rhythm is healthy if it creates clarity, momentum, and correction.
Score the team on:
- Shared ownership.
- Clear priorities.
- Visible work in progress.
- Planning cadence that matches the business.
- Retrospectives or equivalent learning loops.
- Honest estimation or forecasting.
- A method for handling technical debt.
Scrum and Kanban are both useful reference models. Pick the operating system that fits the team. Then run it seriously.
For very small teams, a daily written update may beat a daily meeting. For cross-functional teams, a short standup may prevent days of drift. For chaotic founder-led teams, the main missing piece may be a weekly prioritization ritual.
Good signal: anyone can see what matters this week and why.
Bad signal: engineers are busy, but nobody can connect the work to a company goal.
10. Technical debt as a portfolio
Technical debt is not a moral failure. It is a financing mechanism.
The question is whether the team knows what it borrowed, why, and when repayment becomes cheaper than carrying the risk.
Score debt management on:
- Visible debt register.
- Owner for each major debt item.
- Business risk attached to debt.
- Trigger for repayment.
- Agreement on intentional shortcuts.
- Separation between messy code and dangerous code.
- Ability to delete or replace disposable parts.
This is especially important now because AI makes implementation more disposable. I am comfortable throwing away code. I am not comfortable throwing away intent, tests, data boundaries, or observability.
Some startup code should be temporary. The healthcheck should identify which parts are allowed to be temporary and which parts must be trustworthy.
Good signal: the team can name its biggest debt and explain why it has not been paid yet.
Bad signal: every shortcut is called "startup speed."
The final score is not the answer
At the end of the workshop, calculate the average score if you want. It is useful for a snapshot.
But the score is not the real output.
The real output is the action plan:
- The top five risks.
- The evidence behind each risk.
- The business consequence if ignored.
- The owner.
- The smallest fix.
- The proof that the fix worked.
A fractional CTO should not leave the room with a beautiful audit and no changed behavior. The job is to turn the company from "we hope this works" into "we know which parts are safe, which parts are risky, and what we are doing next."
That is what good startup engineering feels like.
Not heavy. Not chaotic. Clear.