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:
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:
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.