October 04, 2016

Launching a new product – from zero to native couponing

Recently, we successfully launched native couponing in our Android and iOS Apps. Providing coupons with discounts in various areas provides benefits to the approximately 1 million people who use our mobile services on a regular basis. Our users collected more than 15,000 coupons in just the first couple of weeks after launch.

Launching a completely new product is always a challenge, especially if you have a lot of stakeholders – product managers, digital advertisers, sales people, developers, quality assurance specialists, etc. just to name a few. All of them are involved in building great products for our users.

From the viewpoint of a technical project lead, it is challenging to meet all the functional and non-functional requirements. This blog post shows how we bootstrapped a new product from the technical side, from zero to getting it into production; which technology we used; which architecture fits our requirements; how we embedded it in the existing infrastructure; and, most importantly, what to avoid. This article will cover these topics at a high level and will not provide any implementation details.

The product

The business requirements for native couponing are easily explained. Users can browse and collect coupons in our native apps and use them, for example, in a shop to get a discount. These coupons can be browsed in various ways, such as sorted by vendor (“show me all discounts for this shop”) or sorted by date of expiry. The coupons normally have a bar code that is scanned at the shop. The whole product is described here.

Non-functional requirements
With all products that include external partners, there are fixed deadlines. Among other concerns, we had contracts with our partners and advertising plans that were already booked. In short, delay was not an option. Furthermore, the actual costs of the project needed to be as low as possible, since we did not know if the product would be a good market fit. The product also needed to scale on the technical side, because we have a lot of users.

Even on less complex projects, you have to get a lot of things right, and there are some things you simply cannot do if you hope to be successful.

What not to do during a time-critical product launch

System integration
As I mentioned above, we provide coupons for our users. From a technical point of view, these coupons have to get into our system somehow. Unexperienced technical project leads would start to integrate systems. Let’s take a closer look at this scenario. We provided coupons from about 20 vendors at our launch. If we wanted to automatically get all the coupons from them, we would have to integrate 20 different systems, dealing with all the overhead for each, such as APIs, testing system integration, and figuring out why they may not be working in the beginning. System integration is always a time-consuming task, and this task 20 times is a lot of workload to handle. Even if a project like this does not take a lot of implementation time, the throughput time can be very long (e.g., waiting for answers from other companies). For our first version, we entered the coupons manually. No system integration – no worries.

Wait for the API to complete
Our mobile developers had a jump start. Because this was a project launched first on mobile devices, the apps already had a user interface. Normally, an API is defined and then the clients start to integrate it. We did it the other way around. Mobile first means mobile first – the mobile clients designed what API they needed, and the back end was provided for them later in the project accordingly.

Try to cover unneeded features
As previously mentioned, our app shows bar code images. These bar codes are provided as numbers, and, due to scaling reasons, we create them on our servers for the different screens of the end-user devices. There are a couple of hundred different bar codes. Sales, of course, wanted to support them all at launch, but this would have produced a lot of work just to support many codes that were not yet in use. We worked with our partners to figure out the most-used bar codes and only supported those in our first version.

Wait too long for production setup
We got our production environment up and running as soon as possible. We filled it with real data and did a lot of testing there. Caching, timeouts, memory issues, production data, network settings – all are different in the production environment. If you figure out a couple of hours before launch that you forgot to open a port on the firewall – good luck.
After this list of high level “do nots,” let’s get a bit more technical and have a look at the system architecture of native couponing.

System architecture and design
A good system architecture should support businesses in developing adaptable IT landscapes. At willhaben, we build most of our new products as components. These components are embedded in an existing infrastructure that takes away a lot of aspects that otherwise would slow down the development process. For example, authentication, authorization, and saving statistical and historical data are handled by other components already in place that have an easy to use interface. For this reason, these processes are normally integrated in just a couple of hours. The figure shows how the data passes through the system. Another major advantage of this architecture is the portability of this component. As willhaben is part of a larger family of companies that may also want to use this component, it is quite easy to integrate it in their existing systems.

Reporting and statistics are handled by sending events sent via Apache Kafka. Reporting is only done using this statistic component, and never by, for example, holding and evaluating historic data in the production database for native couponing. This helps to keep the database small and avoids complicated dependencies from external systems on the database schema.

As shown in the figure, native couponing was built as a stand-alone component using its own Postgres database, our standard spring-boot stack, and a couple of other internal libraries. Using this stack, which we use on all other components, we were pretty fast in getting the project setup up and running. Using frameworks like Swagger for automated API documentation made it fast to integrate the apps and our backend. Using the same technology and a standard stack also had an advantage, in that even during the summer, when the critical phase of the project took place and a couple of developers were on vacation, we could easily roll developers from other projects on and off this project as we needed them to meet our deadlines with almost zero ramp up time. Our architecture was proven once more to fit our business needs very well.


Native couponing has been quite a success in many ways. It is a perfect market fit for the product. Furthermore, the launch of the product was very straightforward, due to the decisions we made as described above. Thanks to our existing components, we could reuse the functionality and focus on the product itself, developing features instead of infrastructure functionality. This sped up the whole development process and gave us room to improve and ensure the quality of the product. Launching a new product can be a challenge. Saying no to features that are not really necessary for the first product during the development stage is just as important as getting the features right that are implemented and shipped in the first version. As the technicians, we are part of a bigger team and only one piece of the puzzle. With that in mind, decisions related to system architecture, design, and technology must not only fit the developer’s needs and beliefs, but also fit into the higher purpose of building a great product as a team.

No comments:

Post a Comment