Spring Sale! Up to 40% off your matchmaking experience. Limited time offer.

Tawkify Engineering - Tech Stack & Principles

Introduction

At Tawkify, we've achieved a degree of product-market fit, but we recognize that continued success hinges on our ability to innovate rapidly. Our approach to engineering, therefore, blends the stability of established practices with the agility of a startup. This document articulates the principles that guide our technology choices, ensuring that our team remains aligned, efficient, and focused on delivering maximum value to our users.

Our Core Engineering Principles

Our technology decisions are rooted in these core principles:

  • Speed of Iteration is Paramount: We prioritize the ability to move quickly, test hypotheses, and iterate on features. This requires minimizing overhead and maximizing the time engineers spend on delivering user-facing value.
  • Simplicity as a Virtue: Simplicity is not just preferred; it's essential. Code should be easy to write, read, and rewrite. We avoid over-engineering, recognizing that user feedback is the most reliable indicator of a feature's success.
    • Premature optimization examples:
      • writing generic/abstract systems before the feature needs to scale
      • using caches or other performance solutions before we identify the bottleneck
  • Minimize Cognitive Load: We aim to reduce the amount of time developers spend making low-level decisions or wrestling with unnecessary complexity. Our tech stack is chosen to streamline common tasks and free up mental bandwidth for higher-level problem-solving.
    • This comes into play when choosing to add a library: it is valuable if it helps reduce the amount of lines of code in the project, but not when it introduces more complexity than the task itself requires.
  • Embrace the Mainstream: We favor widely adopted, open-source technologies. This provides access to a large talent pool, extensive community support, and better integration with emerging AI-assisted development tools.
  • Code as a Liability, Not an Asset: We view code as something to be minimized. Every line of code introduces potential maintenance burdens and complexity. We want engineers to be intentional when adding a line of code, not writing them out of a habit.
  • Data Model as the Foundation of Simplicity: A clean, well-understood data model is fundamental to a simple and maintainable system. We prioritize evolving the data model and migrating data over adding complexity to our application code to compensate for an outdated design. This approach benefits not only engineering but also product, data, and analytics teams, who rely on the data model.
  • Design for AI Assistance: We believe that AI will increasingly augment software development. We choose technologies and practices that make our codebase easily understandable and navigable by AI tools, enabling our engineers to leverage these tools effectively.

Technology Stack Rationale

Here's a breakdown of our core technologies and the reasoning behind their selection:

  • Frontend Framework: React
    • Rationale: React's popularity ensures a large pool of skilled developers. Its component-based architecture promotes code reusability and maintainability. Its concepts are relatively easy for non-engineers to grasp, facilitating communication and collaboration across teams.
  • Main Language: JavaScript
    • Rationale: JavaScript's ubiquity means a vast talent pool and a rich ecosystem of open-source libraries and frameworks.
  • Type System: TypeScript
    • Rationale: TypeScript enhances JavaScript with static typing, leading to:
      • Fewer runtime errors and easier debugging.
      • Reduced technical debt by improving code maintainability and refactorability.
      • Less need for extensive documentation, as type checking does a better job at explaining a contract than documentation does.
      • Increased developer confidence when modifying existing code.
  • Backend-Frontend Communication: tRPC
    • Rationale:
      • tRPC: Eliminates the need to write and maintain API contracts (e.g., OpenAPI), significantly reducing boilerplate code. Provides strong end-to-end type safety, improving reliability and developer experience.
  • Frontend Application Framework: Next.js
    • Rationale: Next.js provides a robust framework for building React applications, with features like server-side rendering, routing, and API routes. Its convention-based approach streamlines development and promotes best practices.
  • Backend Application Framework: Nest.js
    • Rationale: Nest.js is a Node.js framework that provides a structured approach to building scalable, maintainable, and testable server-side applications. It promotes modularity, uses TypeScript, and encourages the use of established design patterns.
  • Database: PostgreSQL
    • Rationale: PostgreSQL is a powerful, open-source relational database that offers:
      • Reliability and data integrity.
      • Advanced features like vector storage and computation, which may be crucial for future AI/ML initiatives.
      • Support for complex data structures like array types.
      • A strong open-source community and extensive documentation.
      • Overall, it's a more feature-rich and future-proof choice than MySQL.
  • ORM: Prisma
    • Rationale: Prisma simplifies database access with a type-safe and intuitive API. It provides:
      • Automatic type generation, reducing the risk of errors.
      • A focus on developer experience and productivity.
      • Strong alignment with our principle of minimizing code and complexity.
  • Styling Framework: Tailwind CSS
    • Rationale: Tailwind CSS is a utility-first CSS framework that aligns well with our principles. It is simple, well-adopted, and well-known by AI tools. It allows us to define standards and add overrides when necessary.

Guiding Principles for Future Technology Adoption

When evaluating new technologies, we will prioritize those that:

  • Reinforce Simplicity: Reduce complexity in our codebase and development processes.
  • Enhance Developer Velocity: Minimize boilerplate, reduce cognitive load, and accelerate feature delivery.
  • Offer Strong Community Support: Ensure ample resources, a large talent pool, and long-term maintainability.
  • Improve AI Compatibility: Facilitate the use of AI-powered development tools.
  • Minimize Code Output: Reduce the amount of code we need to write and maintain.
  • Support Data Model-Driven Development: Favor solutions that allow us to evolve the data model over adding complexity to application logic.

Conclusion

This technology philosophy is a living document that reflects our commitment to building a high-performing, efficient, and future-ready engineering organization. By adhering to these principles, we empower our engineers to deliver exceptional value to our users while maintaining a sustainable and enjoyable development experience.