Although there are many document generation software solutions available on the market, in some cases building a custom solution makes perfect sense, especially for enterprises. A custom solution will be tailored to the client’s needs, while ensuring high security and personal data protection. Additionally, it will be possible to develop it further, adding new functionalities. Read our story on how we built a custom legal document generation solution for one of our clients.
Having previous experience in similar solutions, we were asked by our client to build a custom legal document generator that would also allow them to sign generated documents electronically. One of the key requirements for the system was scalability and the possibility of handling large numbers of files.
The system should work as follows.
A user fills in the form containing all the data that should appear on a legal document. Based on this data, the system generates a document using an appropriate template. Then, the document is sent to be signed electronically to the email address specified in the data form filled in by the user. When the document is signed, the system downloads and archives it. Additionally, the system should allow users to display a list of documents with their current statuses.
A custom document generation solution—architecture
We decided to base the system architecture on microservices to ensure its scalability and split the development process between several different development teams. Each microservice was responsible for a specific functionality and had its own data source.
For communication with a frontend app, we used Ocelot, an API Gateway that is one central place where we could put authentication, monitoring, and all other mechanisms shared by microservices. Ocelot also allowed us to ensure the system was secure. available for direct communication, it was impossible to exploit potential security vulnerabilities.
API Gateway works in a simple way. Once it gets the query from the frontend (e.g., a list of processed documents) or sends the data from the form to the backend, it splits it into multiple requests and sends them to the appropriate addresses. In this way, we can better manage the traffic in our system and enhance its security, as most of the tools of this type protect us from the most typical attack methods.
For communication between services, we used a service bus. For our system, we chose RabbitMQ with an abstraction layer provided by MassTransit. A service bus is a channel that connects message producers with their recipients regardless of the technology in which they were created. It allows you to set up a message queue and define appropriate paths for messages.
In our document generation system, MassTransit was an abstraction layer allowing us to use any service bus, e.g., RabbitMQ or Azure Service Bus. When you add a message to a queue, you do not need to worry about the service bus you are using, as MassTransit works as an intermediary that supports different ones. In this way, you can stay flexible when adjusting tools to the client’s infrastructure.
Fig 1. The architecture of a custom document generation system.
The workflow of a document
We decided to use a state machine for communication between microservices. A document should move from a microservice accepting the user’s request to a microservice responsible for document generation, and then to a microservice handling electronic signature, etc.
A state machine is a simple yet powerful life cycle tool. In this case, our model was based on the states a document could have in the process and the transitions between them. The transitions were activated once a specific event occurred.
In the custom document generation system we designed and built, there are two types of events. The first one is an event that changes the state of a document. For example, if a document has the state “Document generating,” it can be changed only by the “Document generated event.” Once such an event occurs, the document moves to the next state.
There are also events informing the system that something is happening with the document, e.g., “Document sent for signing event.” If an event of this type occurs, the state of the state machine does not change, but the API that handles the process of signing a document can notify stakeholders that the document was sent for signing and is now waiting for a user to complete the action. In reaction to such an event, the API can change the status of the document to “Waiting for signing” in its database.
MassTransit has a built-in state machine on which we based our custom document generation system.
Fig. 2 The document workflow.
Challenges to overcome when building a document generation system based on microservices
Of course, it was not all plain sailing. Microservice architecture presented us with some challenges we needed to overcome.
First, we needed to design the system in a way that would allow each development team to focus on one functionality based on one microservice. Additionally, we needed to define the interfaces used to exchange data.
Communication was especially important here. We needed to ensure that the system allowed us to scale specific services up or down, e.g., document generation, depending on the current user needs. If communication is designed well, adding new document generators to scale up the workload of the system should go smoothly.
While implement a microservice architecture, you should also use monitoring tools to get insight about what is happening in the system. From a plethora of solutions available on the market, we chose open-source ELK stack that allows you to collect, process, and visualize data effectively.
Our client also wanted to implement the function of sending documents to a specific email address and having them signed electronically. We decided to use DocuSign, which worked well with our solution.
Using one of the microservices, we integrated our solution with the eSignature REST API provided by DocuSign. When a user requests a document be signed, the user that has to sign it gets an email notification. Then, he or she launches DocuSign to sign the document. A microservice integrated with the eSignature REST API checks document batches according to a given time interval, and processes further those that have already been signed. This approach was imposed by the security requirements, as the system was not to be accessible from outside.
Building document generation software—takeaways
The legal documents generation system was an interesting challenge.
Since scalability was one of the key client’s requirements, we needed to use an architecture that could fulfill these expectations. Therefore, we chose microservices. This choice, on the other hand, posed other challenges, such as designing the system architecture, defining the scope of work for individual development teams, and the use of interesting technologies like a service bus.
Microservices that have been popular for some time work well in solutions of this type, but bear in mind two caveats. First, you need to clearly define which microservice is responsible for which feature and, based on this, define the scope of work for each development team, so that it has clear goals and can work autonomously. Second, it is necessary to carefully plan the communication between microservices, so that the final document generation system works well, while remaining flexible for any changes.
Last but not least, the system domain, i.e., automatic document creation, was interesting and presented us with interesting problems to solve, e.g., related to electronic signatures.
To sum up, the project of building a system for automatic generation of legal documents was an interesting endeavor, both technologically and from a business perspective.