TLDR Version

A business application is production-ready when it fits how work actually moves between people and systems, and when its data ownership, security, failure handling, release process and operating model are all defined and tested. Visual polish and a feature checklist are not the measure.

For a mid-sized services company running orders, approvals and reporting on spreadsheets and email, it means a custom application that integrates with the existing ERP and can be run and changed after launch.

The challenge: software must fit the operating model

Off-the-shelf tools work well when a process is served by standard functionality. Custom development becomes relevant when a workflow, integration, role model or constraint cannot be handled without heavy workarounds. Typical symptoms include information re-entered across spreadsheets and applications, different teams holding different versions of a record, approvals that are hard to track, exceptions handled outside the system, reporting that needs manual consolidation, and a growing application that is hard to change safely. These are common patterns, not claims about any particular customer.

Start with the workflow, not the screen

Map the work from trigger to outcome before designing interfaces: actors, decisions, required data, approval points, exception paths and the system of record. Decide which steps to automate, which need human judgement and which existing systems stay authoritative. A request is not “complete” because a form was submitted. It is complete when validation passes, an authorised person approves, downstream records update and the user can see the resulting status. Capture that as acceptance criteria.

Engineering approach

Process flow
  1. Start

    Workflow map and acceptance criteria

  1. Domain model and data ownership

  1. Roles, permissions and exception paths

  1. API and integration contracts

  1. Build with tests around high-risk workflows

  1. Instrument: logs, metrics, alerts

  1. Staged release with rollback plan

  1. Outcome

    Handover: runbooks, decisions, ownership

  1. Define the domain and data ownership. Identify entities, relationships, lifecycle states and authoritative sources. Prevent duplicate or contradictory records with validation, identifiers and ownership rules.
  2. Design around roles and exceptions. Define what each role can view, create, approve, amend and export, including denied actions. The server must authorise every protected operation, not just the interface.
  3. Establish integration contracts. Define schemas, error handling, timeouts, retries, idempotency and versioning. Treat downstream failure as normal, so a partial failure never leaves users unsure whether a transaction completed.
  4. Build for testability. Separate domain logic from interface and integration code, and test high-risk workflows at unit, integration and end-to-end level with realistic but non-sensitive data.
  5. Instrument the application. Log events with correlation identifiers, monitor latency, errors and dependency health, and assign alert ownership so a failure is investigated rather than merely noticed by users.
  6. Plan release and rollback. Use controlled environments, repeatable deployment, migration plans, backup and recovery, and a rollback strategy that suits the architecture.
  7. Hand over for maintainability. Provide architecture decisions, environment configuration, deployment instructions, runbooks, known limitations and ownership boundaries.

Architecture decisions that deserve scrutiny

There is no universally correct stack. The architecture should follow scale, data sensitivity, rate of change, team capability and operating requirements.

DecisionQuestions to answer
Monolith or distributed servicesDoes independent scaling or deployment justify the extra operational complexity?
Relational or non-relational storageWhat consistency, query, relationship and transaction needs exist?
Synchronous or asynchronous integrationWhat latency, retry, ordering and failure semantics are needed?
Managed cloud or self-managed infrastructureWhich fits security, cost, portability and operational capability?
Role-based or attribute-based accessWhat rules govern access to records and actions?
Build or buyIs the requirement genuinely differentiating, or can a standard product meet it at lower lifecycle cost?

A useful case study explains the decisions that mattered and the trade-offs accepted. A long technology list is not a substitute.

How to validate production readiness

AreaEvidence to collect
Functional acceptanceSigned-off scenarios, including important exception paths.
Data integrityValidation rules, transaction tests and reconciliation results.
SecurityAccess-control tests, dependency review and relevant security checks.
PerformanceLoad profile, test conditions, response-time distribution and bottlenecks.
ReliabilityFailure-injection results, recovery behaviour and dependency timeouts.
DeploymentRepeatable release procedure, migration checks and rollback evidence.
OperationsMonitoring coverage, runbooks, alert ownership and backup and recovery tests.
AdoptionUser feedback and actual usage measures, where available and permitted.

Words such as “scalable”, “secure” or “enterprise-grade” should carry a testable meaning. Without the relevant design and validation they should not be used.

Reporting results honestly

Use real before-and-after measures where they exist: time to complete a workflow, manual hand-offs, duplicate-entry rate, processing errors, support incidents, release frequency or time to recover. Define each metric, its observation period and source. If there is no baseline, report delivery facts and acceptance evidence instead of manufacturing a return-on-investment story.

The Neuromotion perspective: the first release should be small enough to measure, with the workflow and failure points agreed before any screen is designed.

Next step: If a business workflow is held together by spreadsheets, email and repeated data entry, start with the workflow and its failure points to judge whether custom software is justified.