The internal ticket tool you are about to build
It starts as a table and an admin page. Then it needs an approval step, then a second approver, then roles, then a record of who approved what and when it ran. Latch Workflow is that system already written: a ticket queue - or a case queue, if you work in a regulated function - with approvals, role separation, an audit trail, and a plugin interface in TypeScript and Go for the parts that are actually yours. It runs self-hosted, which is usually why the build was on the table in the first place.
What you write either way
Teams about to build a ticket queue
You have a spreadsheet, a Slack channel, and an admin page. The next request is an approval step. That is where internal tooling stops being a weekend and becomes a roadmap item.
Teams already maintaining one
Somebody built the queue two years ago and it works. It also has no audit trail an auditor will accept, no separation between requester and approver, and one engineer who understands the state machine.
Teams that ruled out SaaS on deployment
You priced hosted help desk tools, hit a data residency rule or a security review, and concluded that building was the only way to keep ticket data inside your boundary. Self-hosting removes that reason.
Six things you would write before the first ticket closes
None of these are hard. All of them are long, and none of them are why your company exists. This is the work an internal ticketing tool absorbs before it does anything specific to your business.
The queue itself
Assignment and reassignment, priority, SLA timers, an escalation policy that fires when nobody picks a ticket up, and reopen semantics that do not lose the original thread.
Approvals that hold under pressure
Thresholds, delegation when the approver is on leave, expiry, two-person review so the requester cannot approve their own ticket, and denial recorded as an outcome rather than as silence.
A role model with the exceptions in it
RBAC is a day of work until the first exception: break-glass access, a reviewer who can read a ticket but not act on it, and a manager who inherits a queue mid-handover.
An audit trail somebody can defend
Append-only history, denied attempts kept rather than discarded, the exact reviewer path, and the response the downstream system returned when the action ran. Reconstructing that from application logs after the fact does not survive review.
Intake from more than one channel
Email threading and deduplication from a shared inbox, an API for internal services, a web form, and the ticket routing rules that decide where each one lands.
The surface nobody scopes
Search, saved views, bulk actions, notification preferences, on-call handover, exports for the finance team, and the admin screens for every one of those.
The usual reason platform teams accept that cost is deployment. Hosted help desk tools want the ticket data in their cloud, so building looks like the only way to keep it inside the boundary. Self-hosting removes the trade: the queue, the approval workflow, the audit trail, and the models all run on your infrastructure.
Four ways to make Latch yours
The system is designed to be extended, not forked. Plugins, models, and deployment are configuration points rather than escape hatches bolted onto a closed product. The SDK and API reference covers the contract in detail.
Plugin SDK in TypeScript and Go
Write discover and execute functions in the language your team already uses. The SDK handles the contract with Latch - serialisation, auth, response formatting - so the plugin stays focused on the action.
Bring your own model
Plug in your own classification, routing, or risk-scoring model: a commercial API with your own key, or an open-weights model on your own hardware. Swapping it is a configuration change, not a migration.
Self-hosted, private cloud, or air-gapped
Run the whole ticketing system inside your own environment. Ticket data, model inference, and identity stay inside your boundary, which answers the data residency question without a build project.
Every plugin action inherits the controls
Permissions, approval gates, and immutable logging apply to a plugin action automatically. You write the business logic. You do not build a separate auth or audit layer per integration.
What teams ship in the first week
These are not roadmap items. They are workflows teams stand up in days using the SDK, one plugin, and the ticket lifecycle that is already there.
Refund behind an approval
A plugin calls your payment processor. The action runs only after a second reviewer approves it, and the ticket records the request, the approval, and what the processor returned.
Internal fraud review queue
Bring your own risk-scoring model to triage incoming tickets. Latch routes flagged tickets to the right reviewer, keeps requester and approver separate, and records the decision either way.
Vendor bank-detail change
A plugin updates the ERP after approval. The ticket carries who requested, who approved, what changed, and what the ERP returned, without a second system to cross-check.
The quarters you get back
The queue, the approval engine, the role model, and the audit trail are already written and already tested. Your team writes the plugin actions that are specific to your business.
Buying does not mean handing over the data
Run it on your own hardware, in your private cloud, or air-gapped. Ticket data, model inference, and identity stay inside your boundary, so a data residency rule is no longer a reason to build.
The part nobody estimates
Somebody keeps the escalation policy, the SLA timers, and the audit export working through every schema change and every new reviewer role. That ongoing work is what an internal tool actually costs.
Questions platform teams and startup engineers ask
These come up when a team is deciding whether to write its own ticketing and approval layer or extend one that already exists.
We were going to build this on Postgres in a sprint. What are we missing?
Not the queue. A tickets table, an owner column, and a status field is genuinely a sprint. The cost arrives afterwards: the second approver, the reviewer who can read but not act, the denied attempt somebody needs to produce a year later, email intake that threads correctly, and the admin screens for all of it. Then that code needs an owner for as long as the workflow exists.
Is this a Retool alternative?
Partly, and Retool is the better tool for part of the job. For a read-mostly admin screen over a database, it ships faster and Latch is the wrong shape. What an internal tool builder does not give you is a ticket lifecycle: an approval state machine, role separation between requester and approver, an append-only audit trail, and SLA management with an escalation policy. Teams commonly keep their internal admin screens and move the approval-bearing workflows here.
When is building the right call?
When the queue is the product you sell, or when the workflow is one form, one status field, and no approval. Then a table and an admin page is the correct amount of system, and buying anything is overhead. The build stops being cheap at the second approver and at the first request for evidence.
What languages does the SDK support?
TypeScript and Go. Both handle discovery, execution, auth verification, and response formatting, so plugin code stays on the action logic.
Can we run our own models without ticket data leaving our network?
Yes. Deploy on-prem or in your private cloud and point Latch at models running inside your own boundary, including air-gapped installations. The approval gates and the audit trail work the same regardless of where the model runs.
How do plugins get permissions and audit logging?
They inherit them. Every plugin action passes through the same role checks, approval gates, and immutable logging as any other action on the ticket. There is no per-plugin auth layer to write or to keep in sync.
Can we start managed and self-host later?
Yes. The deployment model is separate from the workflow definition. Moving from managed to on-prem does not require rewriting plugins or redefining ticket workflows.
How long until the first plugin runs?
Most teams ship a working plugin in a day. The SDK includes a local test harness that simulates ticket context and role checks without a running Latch instance.
See the queue you were about to build
Walk the ticket lifecycle end to end - intake, routing, approval, plugin action, audit trail - and decide what is left for your team to write.