How to Build a DIY Ticketing System
In this post, we'll look at how to build your own ticketing system, as well as provide a few recommendations to get you started.
What Exactly Is a Ticketing System?
A ticketing system is what you need once leaving tasks in your email inbox or on your to-do list is no longer keeping up with your workload. In this post, we'll look at some of the questions you'll want to ask yourself in deciding whether, and how, to build your own ticketing system, as well as provide a few recommendations you can base your plans on.
A ticket is created whenever something needs to be done and tracked—this could be issues with a codebase or tech-support tickets created when a customer calls. A ticket has at least an ID (the ticket number), a status (active or complete), and a description. The second core concept of a ticketing system is the agent, a registered user who can be assigned a ticket and can then handle the issue and close the ticket. Finally, almost every ticketing system provides comments on tickets, although they may be internal to the organization. We'll go into a little more detail in a minute, but there's another question we have to ask first.
Why Build Your Own Ticketing System?
Should you even be reading this post in the first place? Probably! The benefits of rolling out your own system are clear: you have complete control over your ticket data, you can customize displays and lists to meet your specific needs, and your private ticketing system can be integrated completely into both your customer-facing website and your internal systems.
You're free to decide what the system will do when tickets are created, when tickets are closed, and even when tickets change status. Maybe you want to raise a ticket automatically when a customer sends an email to a specific address, or maybe you want full control over notifications sent out when people make changes to tickets. Whatever your needs, you can do it if you own the code.
The flip side of that equation is that you'll be on the hook when things go wrong, and your staff may need to wait for issues to be resolved. They may find it only minimally amusing if you tell them that you've raised a ticket for their issue. And if you use an existing ticketing service, of course, you could be up and running before you've even finished reading this post.
But let's assume you're going to build your own system.
The Basic Feature Set
The first thing I do when I start planning a new system is to take a look at what other people have done, to distill a common set of features that make sense to me. From there, it's easy to get to the entity-relationship diagram describing the different objects in the system, and from that we can derive the API we'll expose. This approach has the advantage that there are always some features that you simply haven't thought of yet. You also get a first cut at a future road map, with core must-have features to implement immediately and things you might add later should time and necessity permit.
You can pick any number of existing systems; to prepare for this article, I looked at two open-source systems (Ticketit and osTicket), as well as Wrangle, a commercially available ticketing service plugin for Slack. To save space, I'll skip the detailed feature analysis—I already defined the three core entities of any ticketing system at the start of this post, shown in more detail in the figure here, and below I'll touch briefly on a few other features you might find useful. First, though, I want to talk about how the semantic entities in a system determine the API it should expose.
Back-End Functionality and Front-End Presentation
Current best practice in any kind of internet-facing application is to put your business logic into a back end with an API, then build your in-browser presentation separately. Aside from keeping your concerns (functionality vs. presentation) separate, there's an advantage to this that may not be immediately obvious. If you build your system on an API, it will be easy to have other software talk to it to get things done. You won't be locked into a particular presentation, and things like raising tickets from an email queue or running periodic checks from a command-line script are almost trivial.
The API also hides implementation details from your caller—your API talks in terms of tickets and users, so you can change the database structure any time you need to without changing any other code. I also find it easier to think about features in terms of the API I'll need to implement them.
Once you've defined the back-end API, you can build the front end in the UI framework of your choice. You can serve both the API and the front end from the same server, making deployment relatively painless.
The Nitty-Gritty of RESTful APIs
REST defines "documents" that correspond to the entities in your system. As a general rule, each type of document (each entity) should have its own endpoint. You then use the HTTP method to tell the API what to do with those documents. You're already familiar with GET and POST from normal HTML browsing, but there are three more methods you'll see in REST APIs: PUT, DELETE, and PATCH.
For our minimal ticketing API, then, we'll have these access points:
For tickets and users, the methods have the following meanings:
- GET from /api/tickets retrieves a list of tickets
- GET from /api/tickets/xyz retrieves the ticket with ID "xyz"
- POST to /api/tickets creates a new ticket with a new ID
- PUT to /api/tickets/xyz writes an entire new object to the ticket "xyz"
- PATCH to /api/tickets/xyz writes selected data fields to ticket "xyz"
- DELETE to /api/tickets/xyz deletes ticket "xyz"
Where this API differs from a simple database call isn't immediately obvious. When we GET a ticket, we also get all the comments on that ticket in the same object. We don't even have to implement GET for comments! All we really need is POST to create a new comment in a ticket. We might also want PATCH and DELETE to allow users (or administrators) to edit and delete existing comments. The API allows us a much more natural way of thinking about tickets than a database alone can.
One quick note about lists of objects: always implement pagination right from the start. You'll thank yourself later when you've got more than 20 tickets in the system. Every list return should contain metadata about the number of objects in the list in question, the number actually returned on this call, and where you are in the page list.
The User Interface
- Ticket list: If you implement some search parameters, this can represent multiple queues within your system. At the very least, you'll want separate lists of open and closed tickets.
- Ticket posting form: This is a normal POST form that creates a new ticket.
- Ticket display showing comments and containing a comment post field: Administrators will need to see a more complete display, including a way to assign an agent to the ticket.
- User request form, if you need one, and user lists for administrators.
- Reporting: The number of tickets issued and completed by period, for instance.
DIY Ticketing System: Final Thoughts
There are three key decisions you'll need to make to implement this system. First is the database you'll use to store your ticketing information. Then there's the web server you'll code against and its implementation language. Finally, there's the UI framework you'll use to present information to the user. I built this minimal design using SQLite, Python/Flask, and React so you can get your feet wet. You can browse that code at https://github.com/Vivtek/MVPTicketing and run a test instance by following the instructions on the project page.
The takeaway here? There are a lot of decisions to make about how you want to handle ticketing. If you've found this process daunting, a commercially available product is a viable option. A provider like Wrangle can get you up and running instantly. Either way, a ticketing system can save you a lot of stress in managing the needs of your customers.
This post was written by Michael Roberts. Michael has been slinging code for decades, from GUI to system architecture, database design to compilers, and likes to tell stories about it. He's happiest when given a mess and told to make sense of it.
- Free 14-day trial
- Personalized onboarding
- Access to all features