Software Architecture/Engineering  

Engineering FlowOps: From an Operational Problem to a Working SaaS Product

Many of the engineering projects I worked on earlier in my journey were focused on infrastructure, automation and developer platforms. They taught me how to think about reliability, workflows, permissions, state, automation and operational visibility.

Eventually, I wanted to apply those ideas to a problem outside traditional infrastructure engineering.

I kept seeing a common operational pattern in service based businesses: customer requests arrived through different channels, jobs were coordinated manually, team communication was fragmented and customers often had limited visibility into what was happening.

That problem became the starting point for FlowOps.

FlowOps is a service operations product designed around one central idea: bring customer requests, jobs, teams, workflow status, communication and service delivery into one structured operational workspace.

In this article, I will share how I approached the engineering journey from identifying the problem to designing and building a working multi tenant SaaS product.

Product Journey

Operational Problem

Workflow Research

Product Requirements

Multi Tenant Architecture

Roles + Permissions

Job Lifecycle

Customer Tracking

AI Assisted Request Capture

Working SaaS Product

Start with the Problem, Not the Features

One lesson I carried from platform engineering into product development was that technology should not be the starting point.

The starting point should be the problem.

The problem I wanted to understand was:

How can a service business manage the complete journey from customer request to completed service without depending on disconnected messages, spreadsheets and repeated manual coordination?

Once I framed the problem this way, the product requirements started becoming much clearer.

Understanding the Operational Actors

Before designing screens, I wanted to understand who interacts with the workflow.

The main actors became:

Owner
Controls the business workspace and has full operational visibility.

Manager
Coordinates work across their team and manages relevant operational tasks.

Team Member
Focuses mainly on work assigned to them and the jobs they are responsible for.

Customer
Receives service updates and limited tracking visibility without needing access to the internal business workspace.

These actors became the foundation for the permission and workflow model.

Designing FlowOps as a Multi Tenant Product

Because FlowOps is designed for multiple businesses, tenant isolation became one of the first architectural requirements.

Each organisation needs its own:

  • Users

  • Customers

  • Jobs

  • Team structure

  • Messages

  • Operational history

  • Dashboard information

A simplified organisation record could look like:

{
  "tenant_id": "tenant_2048",
  "business_name": "Example Services Ltd",
  "status": "ACTIVE"
}

Business data is always associated with the correct tenant.

Role Based Product Behaviour

I did not want FlowOps to treat every internal user in the same way.

Different users have different responsibilities.

A simplified permission model could look like:

ROLE_ACCESS = {
    "OWNER": {
        "view_all_jobs",
        "manage_team",
        "manage_customers",
        "assign_jobs",
        "review_work",
        "manage_workspace"
    },

    "MANAGER": {
        "view_team_jobs",
        "create_jobs",
        "assign_jobs",
        "manage_relevant_team_work"
    },

    "TEAM_MEMBER": {
        "view_assigned_jobs",
        "update_assigned_jobs",
        "create_own_jobs"
    }
}

The exact product rules go beyond simple role names, but the principle is clear: users should see and control only what is relevant to their responsibility.

The Job Became the Core Operational Object

One of the most important product decisions was identifying the central object around which the workflow should operate.

In FlowOps, that object is the job.

A job connects:

Customer
+
Service Request
+
Assigned Team Member
+
Schedule
+
Workflow Status
+
Operational Notes
+
Review

Job

Designing the Job Lifecycle

I wanted the job lifecycle to represent real service delivery rather than a generic task list.

The workflow became:

Draft

Pending

Scheduled

On Route

Arrived

Started

Completed

Delivered

Each stage communicates something meaningful to the business, the team member and, where appropriate, the customer.

Workflow States Need Rules

I did not want job status to behave like a free text field.

The application should understand what can happen next.

ALLOWED_TRANSITIONS = {
    "PENDING": {
        "SCHEDULED"
    },

    "SCHEDULED": {
        "ON_ROUTE"
    },

    "ON_ROUTE": {
        "ARRIVED"
    },

    "ARRIVED": {
        "STARTED"
    },

    "STARTED": {
        "COMPLETED"
    },

    "COMPLETED": {
        "DELIVERED"
    }
}

This gives the application a real workflow engine rather than simply a set of status labels.

Assignment Needed Business Rules

Assignment sounds simple until real operations are considered.

Questions appear quickly:

  • Who is allowed to assign work?

  • Can a job be reassigned after work begins?

  • Who receives a reassignment request?

  • Should assignment be visible to the customer?

This led to designing assignment as part of the workflow rather than as an isolated form field.

For example, reassignment can remain available during earlier stages, while active execution stages require stronger control.

Completion Is Not Always the End

One of the product decisions I found important was separating work completed from work accepted.

A team member may finish the operational work, but a manager or owner may still need to review it.

Work Finished

Sent for Review

Reviewer Checks Work

Close
or
Reattempt

This gives the product a quality control layer rather than assuming that every completed action should immediately close the job.

Review Routing Depends on Responsibility

The review destination also depends on who created the work.

Conceptually:

IF creator == "TEAM_MEMBER"
THEN reviewer = manager

IF creator == "MANAGER"
THEN reviewer = manager

IF creator == "OWNER"
THEN reviewer = owner

IF manager_is_unavailable
THEN reviewer = owner

This is a good example of a product rule that only becomes obvious after thinking about how real organisations operate.

Customer Tracking Without Customer Accounts

Another problem I wanted to solve was customer visibility.

Customers should be able to understand the progress of their service without being given access to the internal workspace.

The solution was a controlled tracking link.

Job Created

Secure Tracking Link

Customer Opens Link

Limited Job Information

Current Service Status

The tracking experience remains intentionally separate from internal business information.

Tracking Links Need Their Own Security Rules

A tracking link should not become permanent access to operational data.

Conceptually, a tracking record can contain:

{
  "tracking_token": "secure-random-token",
  "job_id": "job_4892",
  "active": true,
  "expires_after_completion": true
}

Once the permitted tracking period has passed, the token should no longer expose the job.

Operational Communication Belongs with the Work

Another problem with manual operations is that important information can disappear into private messages.

I wanted relevant operational communication to remain connected with the business workspace.

Owner

Manager

Team Member

Shared Operational Context

Messaging should support collaboration without replacing the structured job workflow itself.

Designing the Dashboard Around Decisions

I did not want the dashboard to become a page full of decorative charts.

The useful question was:

What information helps someone understand the operation quickly?

Important signals include:

  • Today's jobs

  • Active work

  • Completed work

  • Recent operational activity

  • Short term job volume

The dashboard should help answer what needs attention rather than simply display data.

My Jobs Needed Different Views of the Same Workflow

A single list of every job quickly becomes difficult to use.

The product therefore needs operational views such as:

Today
Upcoming
Active
Awaiting Review
Completed
All

These are not separate datasets.

They are different operational perspectives on the same underlying workflow.

AI Became Useful at the Request Capture Stage

One of the biggest friction points in service operations is converting an unstructured customer request into structured operational data.

A customer may write:

Our air conditioning stopped cooling properly yesterday. Someone can visit any time after 3 PM on Thursday. Please call before arriving.

Instead of manually copying each detail, AI can suggest structured fields.

{
  "service_type": "Air conditioning service",
  "issue": "Unit not cooling correctly",
  "preferred_time": "Thursday after 15:00",
  "customer_instruction": "Call before arrival"
}

The user can review the suggested fields before applying them to the job.

AI Should Fill, Not Invent

This became an important design principle for the AI functionality.

AI can interpret the request and suggest information that is actually present.

It should not invent missing customer details or business information.

Customer Request

AI Interpretation

Suggested Structured Fields

User Review

Application Validation

Job Creation

Keep AI Separate from Workflow Authority

The AI layer should not decide whether a job can move from Scheduled to Completed.

That remains the responsibility of the workflow engine.

AI
→ Interpret Requests
→ Suggest Structured Information

Workflow Engine
→ Validate Status Changes
→ Enforce Permissions
→ Control Business Rules

This separation made the system easier to reason about and safer to operate.

Product Engineering Means Designing Exceptions

Building the product also taught me that the main workflow is only part of the engineering problem.

Real users create exceptions.

Examples include:

  • A team member becomes unavailable

  • The customer reschedules

  • A job needs reassignment

  • The work requires another attempt

  • There is no manager available

  • The customer cancels

Good product architecture needs to support these situations without making the workflow unpredictable.

Mobile Behaviour Became a Product Requirement

Service operations do not happen only at desks.

Team members often need to update jobs while travelling or while delivering the service.

That means the product needs a mobile experience designed around fast operational actions.

View Today's Work

Open Job

Review Customer Details

Update Status

Add Operational Notes

Complete Work

Mobile behaviour therefore needed to be considered as part of the workflow design, not as an afterthought.

Reliability Became More Important as the Product Grew

Once a product becomes responsible for operational work, small failures can create real business disruption.

I therefore needed to think about:

  • Error handling

  • Authentication

  • Tenant isolation

  • Permission enforcement

  • Rate limiting

  • Health checks

  • Operational logging

  • Failed workflow recovery

This is where my infrastructure background became particularly useful.

Building for Maintainability

Product development is not finished when a feature works once.

As FlowOps grew, maintainability became increasingly important.

I wanted to reduce unnecessary duplication, keep components organised and make future changes easier to understand.

Working Feature

Review Structure

Reduce Duplication

Standardise Behaviour

Test Again

Maintainable Product

Product Decisions Are Often Tradeoffs

One thing I learned while building FlowOps is that product engineering is full of tradeoffs.

Adding more features does not always create a better product.

Sometimes removing complexity improves the workflow.

For every feature, I started asking:

Does this solve a real operational problem?

Does it make the workflow easier or harder?

Who actually needs this feature?

Does it create another permission rule?

Does it introduce unnecessary complexity?

Can the same outcome be achieved more simply?

Feedback Changed the Product

Building a real product also means accepting that the first version of an idea is rarely the final version.

Feedback and testing can reveal:

  • Confusing actions

  • Unnecessary screens

  • Missing workflow states

  • Incorrect assumptions

  • Mobile usability problems

  • Permission edge cases

Product engineering therefore became an iterative cycle rather than a one time build.

Build

Test

Observe

Collect Feedback

Improve

Repeat

FlowOps Architecture

Business Users

FlowOps Application

Authentication + Tenant Context

Role + Permission Layer

Customer + Job + Team Services

Workflow Engine

Review + Assignment + Tracking

Notifications + Messaging + Audit

AI Assisted Request Capture

Operational Dashboard

From Engineer to Product Builder

Building FlowOps changed how I thought about engineering.

Earlier in my career, success often meant answering a technical question:

Does the pipeline work?
Is the infrastructure reliable?
Is the deployment automated?
Is the platform easier for developers to use?

Product engineering introduced a broader question:

Does the product solve the operational problem in a way that real users can understand and depend on?

That required me to think about engineering, user experience, workflow design, product decisions and operational reliability together.

What Building FlowOps Taught Me

Several lessons became especially important during the product journey.

Understand the workflow before writing features.
If the operational model is unclear, software only digitises confusion.

Permissions are part of product design.
Different users need different levels of visibility and control.

Status should mean something.
Workflow states should reflect actual business progress.

Customers need the right visibility, not internal access.
Tracking should expose useful information while protecting business data.

AI should assist, not control.
AI is valuable for interpreting requests, while application rules remain deterministic.

Real products need exception handling.
Rescheduling, reassignment, reattempts and unavailable managers are part of real operations.

Maintainability matters.
The product has to continue evolving after the first release.

FlowOps as the Result of an Engineering Journey

Looking back, FlowOps was not disconnected from my earlier engineering work.

Many of the ideas came from the same principles I had already been exploring:

CI/CD
→ Predictable Processes

Infrastructure as Code
→ Repeatable Systems

Kubernetes
→ State and Reliability

GitOps
→ Controlled Change

Platform Engineering
→ Better User Experience

AI Automation
→ Assisted Interpretation

SaaS Architecture
→ Tenants + Roles + Isolation

FlowOps
→ Applying Those Ideas to Service Operations

The Product Today

FlowOps has evolved into a working service operations product focused on bringing the main parts of service delivery into one workspace.

The product brings together capabilities such as:

  • Customer management

  • Booking and job creation

  • Job scheduling

  • Role based team coordination

  • Assignment workflows

  • Structured service lifecycle

  • Customer tracking

  • Review and reattempt workflows

  • Operational messaging

  • Dashboard visibility

  • AI assisted request capture

The larger goal remains simple: reduce the operational coordination required to move a customer request from intake to successful service delivery.

Final Product Architecture

Customer Request

AI Assisted Request Capture

Booking / Job Creation

Schedule + Assignment

Team Execution

On Route → Arrived → Started

Work Completed

Review / Reattempt

Delivered

Customer Tracking + Operational History

Dashboard + Reporting

Conclusion

Engineering FlowOps was an important step in my journey from infrastructure and DevOps engineering into product building.

In this article, I explored:

  • Identifying the operational problem

  • Designing around real users

  • Multi tenant SaaS architecture

  • Owner, Manager and Team Member roles

  • Permission driven product behaviour

  • The job as the core operational object

  • Structured job lifecycle

  • Controlled workflow transitions

  • Assignment and reassignment

  • Manager review and reattempt workflows

  • Customer tracking

  • Operational messaging

  • Dashboard design

  • AI assisted request capture

  • Exception handling

  • Mobile workflow design

  • Maintainability

  • Iterative product development

The biggest lesson for me was that building a product is very different from building a collection of features.

A product has to understand the user's workflow from beginning to end.

Infrastructure, automation, permissions, AI and application code all matter, but they only become useful when they work together to solve a real operational problem.

That is what I wanted FlowOps to become: a structured operational workspace that helps service teams coordinate work, keep customers informed and move jobs through a clear delivery lifecycle.

My next step: Building the first working version of FlowOps was only the beginning. The next challenge was learning how to evolve a real SaaS product safely while adding features, improving performance and responding to user feedback. In my next article, I will explore what I learned from taking FlowOps from an initial working product towards a more maintainable and scalable platform.