Consulting for your web project – what does it get you?

3 March 2025

Our IT consulting service is designed to improve your application and make it stable, reliable, performant and secure. Having dozens of projects under the belt, we’ve developed a structured approach to assessment of web applications.

How We Approach a Project

  1. Understanding the business case – We dive into your application’s purpose, architecture, and key components: backend, frontend, database, and external services.
  2. Optimizing the frontend-backend relationship – We analyze the separation of concerns and identify the best way to make both layers work together efficiently.
  3. Database structure check – We assess database structure, focusing on constraints, indexes, and performance bottlenecks.
  4. API security review – We check the security aspect of the APIs, especially for authentication, but also for threats like CSRF or SQL injection, and features like SSL/HTTPS, and session security.
  5. Test coverage strategy – Together with the client we define core functionality that must be covered with tests.
  6. CI/CD pipeline setup – Whether setting up from scratch or improving an existing setup, we ensure smooth deployments, regardless of the CI or hosting provider.

If a company already has an internal development team, why would they benefit from working with us?

We see your project from a different perspective, with fresh eyes and without first-hand knowledge of reasons for the decisions that have been made. This allows us to remain more objective in the analysis we perform.

Case Study: noxt! engineering’s Django Platform

Recently we got to know noxt! engineering GmbH - a company, specializing in appraisals for windparks. To do an appraisal they have to perform complicated simulations, for example to determine acoustic impact of turbines on the surroundings, and visualize the results.

They have an in-house team of developers, working on a Django application to manage the company’s windpark projects. Information about the windparks is stored there, simulations are requested, their results are saved and visualized all in one place.

Even the best development teams benefit from a fresh perspective. noxt! engineering, wanted to ensure their Django-based platform was built on a solid architectural foundation. Rather than waiting for problems to arise, they took a proactive approach and brought us in to provide expert feedback on their architecture, best practices, and development workflows.

Let’s go into detail for a couple of topics we tackled for them as part of our consulting service. Our goal was to strengthen the overall structure, maintainability, and flexibility of the project, ensuring that development remains efficient, even as the codebase, team, and system complexity grow.

Production database data independence

Sometimes applications get in the state of tight coupling between logic and database data, resulting in a specific database dump being essential to spawn a new (for example development or staging) system.

Usually such dumps are made from the production database. Production data, especially user or business sensitive data, has to be handled with care and not live off in numerous dumps and running systems.

Ideally the application would not be dependent on particular data present in the database to run. This is what we call production database data independence.

To solve the problem we first analyze the data stored in the database to understand what kind of data it is. Usually there are three categories:

  • Data that can be randomly generated, for example users with any name, email, and date of birth.
  • General knowledge data, that you don’t want to generate randomly, for example geographical data. Germany has 16 states and very precise ones with strictly defined geographical borders. Any polygon with a generic name won’t do.
  • Derived data or caches. Such data doesn’t have to be present when the system is spawned and will get calculated and stored on runtime.

For data that can be randomly generated we suggest writing factories, for example with factory_boy, which can be used to generate data for development as well as for tests. We wrote several factories to get the process started.

For general knowledge data that cannot be generated, we find ways of importing it, for example geo data of Germany can be automatically pulled from the sources like https://basemap.de/.

Testing

Testing, both backend and frontend, is what gives you confidence in the implementation, and also reduces development time when extending or refactoring it.

We went through the application and together with the internal development team chose one of the most business critical parts. We wrote different types of tests, unit and integration tests, but also those for different parts of the application: Django models, Django views, API views, utility functions.

We configured the pytest testing framework, extended it with plugins like pytest-mock, pytest-django, wrote factories to create test data, and provided the test examples. This made up a complete testing environment for the internal team to continue to increase test coverage on their own.

Code testability

Testing can be thorough only if the code is written in a way that allows testing. This is called code testability. There are several indicators of the testable code that we went through:

  • refactoring functions that do too many things for example by adding abstractions with small clearly defined behaviours and responsibilities. In a Django application views tend to become mighty functions that do all the processing.
  • adhering to the DRY principle, to reduce logic repetition and thus needing to test it only in one place.
  • checking if we can make non deterministic functions deterministic - ensure that they can return only one output for the given input. In a Django application a function that returns an unordered queryset might be a good candidate.

CI/CD pipeline

When working on CI we pay extra attention to dependency management to ensure that the package versions are the same in all environments. In the current project the simulations are being performed by the package developed by a different development team of the client. We streamlined the build process by switching from direct simulation code pulling to installing it as a wheel.

We tuned the ruff linter configuration, and added Django specific checks, like for example ensuring that no database migration has accidentally been forgotten.

We configured continuous deployment to the staging system when CI passes for merges on main.

What does the client say?

Christoph Lehmann, CTO noxt! engineering GmbH:

“Djangsters quickly understood our challenges and offered fitting solutions. Communication was easy, honest, and to the point. Their practical advice didn’t just solve immediate problems but made our platform more stable, flexible, and ready for the future.”

djangsters GmbH

Vogelsanger Straße 187
50825 Köln

Sortlist