Pular para o conteúdo
← Back to Skalablog

Published article

How to Deploy a Project to Production Safely

Software EngineeringOpenAICursorClaude

To deploy a project to production, start with requirements engineering, then fix your architecture, testing and CI/CD pipeline, documentation, and observability before any code ships. A June 2026 live session from Rocketseat walked through exactly these decisions and benchmarked AI coding tools against a real Go project.

Which choices matter most before you deploy a project to production?

Before you deploy a project to production, the decisions that matter most are requirements engineering, architecture, a test-driven workflow with CI/CD, API documentation, and observability. Hosting comes late in the sequence. A Rocketseat live session broadcast on 18 June 2026 worked through this exact decision order on a real Go backend.

The presenter, a Go developer who works with Laravel, Rails and PHP backgrounds, framed the sequence as a checklist he applies before touching code. His argument is simple: decisions made in the first hours of a project determine how much refactoring you will need later. Good early choices do not eliminate refactoring, but they reduce its probability.

The checklist from the session looks like this:

  • Requirements engineering, to define language, infrastructure and architecture
  • Software architecture, chosen for the expected scale
  • Test-driven development, so confidence in the code is continuous
  • CI/CD with Dockerfile, Docker Compose and separate staging and production workflows
  • API documentation generated from OpenAI, viewed in a modern UI
  • Observability with tracing, logs and metrics from day one
  • Server-side session management for security

Each of these is expanded in the sections below, together with the AI benchmark the live audience watched at the end.

Why does requirements engineering come first?

Requirements engineering comes first because it is the step that reveals which language, architecture and infrastructure the project actually needs. Without it, the presenter argued, a system is built on guesses and the remaining decisions become arbitrary.

He pointed to Mercado Livre as the example the community knows: the platform runs thousands of microservices, and they are not written in a single language. That diversity is a consequence of per-service requirements, not fashion. When requirements are documented, the right language and infrastructure fall out of the analysis instead of being picked from a trend list.

For a community project built on a single VPS, the same discipline still applies at smaller scale: it decided on Go for the backend, a mid-scale architecture, and a straightforward virtual private server deployment rather than a managed platform. Vercel is the managed alternative the live discussion contrasted with self-managed infrastructure, since the platform behind Next.js is the path many frontend developers already know.

MVC, SRC or MSC: which architecture should a mid-scale backend use?

For a mid-scale Go backend, the live session recommended the MSC pattern, Model Service Controller, over both MVC and SRC. MSC keeps the model as both entity and repository, puts business rules in the service, and leaves HTTP concerns in the controller.

Three patterns were compared in the session:

PatternLayersBest fitMain limitation
MVCModel, View, ControllerCoupled web apps like classic Laravel or RailsView and backend are tied together
SRCService, Repository, ControllerLarge, strictly layered codebasesMany files and heavy boilerplate
MSCModel, Service, ControllerSmall to mid-scale teams that need speedModel merges entity and data access

The reasoning against MVC was practical: the same API should serve a website, a mobile app and even a car dashboard, so the view cannot live inside the backend. SRC follows SOLID more strictly but produces a large file tree that slows small teams down. MSC merges the entity and its specific queries, such as findUsername, into one file, which the presenter found more productive for his team size.

He was explicit that MSC is a trade-off: if the entity grows or the project scales globally, splitting it into a separate repository and migrating toward SRC is straightforward, especially with AI assistance. The framework Spring uses an equivalent split, calling its data-access layer a repository rather than a model.

How do TDD and CI/CD work together in this workflow?

TDD and CI/CD work together by putting tests before features in development and before deploys in the pipeline. In test-driven development, you write a failing test first, write the minimum code to pass it, then refactor while keeping the test green.

The live session demonstrated the loop on a user-registration feature: write a unit or integration test that expects a valid name, email and password, watch it fail, then implement the controller, service and model until it passes. The presenter dismissed the idea that TDD means testing after deployment; tests run inside the CI workflow before the deploy step ever triggers.

The pipeline order in the project was:

  1. Push triggers a checkout in the CI workflow
  2. The test battery runs, including unit and integration tests
  3. Only a green pipeline proceeds to continuous deployment
  4. Staging gets a separate deploy workflow, where QA verifies behavior
  5. Production deploy runs as its own dedicated workflow

The codebase supported this with two service constructors: a production constructor wired to the real database and a testing constructor that returns an in-memory mock. That removed the classic pain of mocking databases manually or spinning up staging databases for unit tests.

The presenter also noted that TDD does not require a layered or hexagonal architecture. You can write a single test file that makes an HTTP request and asserts the expected response, which is a common starting point for developers new to the discipline.

What should replace Swagger for API documentation?

Scalar should replace Swagger when the goal is a readable, modern API documentation UI driven by an OpenAI document. Both consume the same OpenAI JSON that tooling generates; they differ in how you explore and test endpoints.

The presenter's critique of Swagger was organizational: the interface is linear, scrolling from top to bottom, so finding an endpoint means searching or pressing Ctrl+F. He also disliked how the test panel presented responses when working from the frontend's point of view. Scalar offers a UI he found substantially better for both navigation and response inspection.

Generation mattered as much as presentation. Writing a giant JSON spec by hand in Go is awkward, so the project used a generics-based HTTP framework that produces the OpenAI document automatically from typed request and response DTOs. DTOs, typed structures for requests and responses, also double as validation: an unexpected field in the request fails before it reaches the controller, which the presenter described as an additional security layer on top of explicit validation.

What is Grove and which libraries did it choose for Go?

Grove is the presenter's own Go scaffolding tool, a boilerplate generator rather than a commercial framework, built to encode the deployment and architecture decisions above. It ships a CLI similar to artisan in Laravel or the Rails command, with a grove setup command that scaffolds the project and a hot-reload configuration for development.

The library choices in the scaffold were deliberate:

  • Fuego, a Go HTTP microframework using generics, chosen because it generates OpenAI documentation from typed handlers
  • Atlas, which converts Go model code into versioned SQL migrations
  • Grafana, Jaeger, Prometheus, Loki and Promtail for dashboards, tracing, metrics and logs, wired up through Docker Compose
  • Jest-inspired test naming conventions, so JavaScript developers feel at home in Go tests

The observability setup merits its own mention. Jaeger traces incoming and outgoing requests and supports custom spans, so a slow user-registration flow can be broken into spans for registration, the confirmation email to the user, and the notification email to the admin. The slow span identifies itself, and the fix is either optimization or moving work into a separate routine.

The presenter stressed that this is a personal scaffold, not a product pitch: he built it because existing Go frameworks such as Kratos, go-zero and Buffalo each solved part of his decision list but not all of it, leaving him writing large amounts of boilerplate on every new project. He also advised checking framework documentation quality before adopting anything, noting that popular projects sometimes ship a great CLI with no explanation of what the CLI does.

Why keep sessions on the server side?

Server-side sessions reduce the attack surface compared with client-side sessions, because attackers cannot tamper with a JWT or a cookie to hit the API directly. The presenter has moved increasingly toward this pattern in his own projects.

His argument: client-side sessions, common in classic Laravel setups, die when the browser closes and can be reversed by anyone who captures the token. With the session stored on the backend and managed through Redis, a 'remember me' feature, fingerprint identification and revocation all become server concerns. The frontend then talks through a backend-for-frontend layer or, in the case of Next.js with React Server Components, through server-side requests only.

The trade-off is that this pattern only works well when your frontend has a server component. A purely static frontend would need a different session strategy, which is exactly the kind of requirement-engineering question the session placed at the start of the process.

Which AI tool performed best in the live benchmark?

In the live benchmark, Cursor produced the best code overall, while Claude 4.6 running inside Google's Antigravity completed the task most reliably. All three tools received the same prompt: analyze the Grove project, then add an articles entity owned by the user, using TDD, security and rate limiting, and following the existing architectural patterns.

ToolModelStrengthMain failure
AntigravityGemini 2.5 FlashFastest to finish, understood the CLIAdded a user ID without the relationship, ignored project test patterns
AntigravityClaude 4.6Most complete delivery, wrote DTOs and unit tests firstCrammed all integration cases into one test battery
Cursorauto model selectionOnly tool that read and followed the project's test patternsGot stuck trying to reinstall Go and needed manual intervention

These results come from one task on one project during the June 2026 live session, and the presenter scored them himself. The Gemini 2.5 Flash run received roughly 4 to 5 out of 10, the Claude 4.6 run about 5 to 6, and Cursor about 6 to 7 for code quality despite never getting its tests to run. One project and one prompt prove nothing about general model quality, so treat the scores as a demonstration, not a benchmark study.

The behavioral differences were as instructive as the scores. Cursor in agent mode acted with high autonomy and only asked for permission in plan mode, which made the presenter uncomfortable when it tried to reinstall Go on his machine. Antigravity asked permission very often, even for a go mod download, which the presenter noted a terminal agent handles without friction. He also observed that Antigravity wasted time opening a browser to take screenshots instead of writing code, and that he uses GitHub Copilot occasionally as a third option.

The broader lesson for AI-assisted work: a well-structured, documented project with consistent patterns is easier for every tool to extend correctly. The tools that read the existing code and DTO conventions produced materially better results than the ones that generated code from the prompt alone.

Frequently asked questions

  • What should I decide before a production deploy? Decide requirements, architecture, testing strategy, CI/CD pipeline, documentation and observability. Hosting is a late decision; the earlier ones determine how safely your code reaches any server.
  • Is MVC a bad choice for a backend API? Not bad, but coupled. MVC ties the view into the backend, which prevents the same API from serving web, mobile and other clients. For a standalone API, a service-oriented split like MSC or SRC fits better.
  • Do I need a layered architecture to practice TDD? No. You can write a single integration test file that makes an HTTP request and asserts the response. Layers make mocking easier, but the discipline of test-first development works anywhere.
  • Why use TDD if QA tests after deployment anyway? TDD gives continuous confidence during development and catches failures before the deploy step in CI. QA then covers what automated tests cannot see, such as communication failures between frontend and backend.
  • What replaced Swagger in modern API workflows? Swagger UI still works, but many teams now render the same OpenAI document with Scalar, which offers better navigation, search and response inspection during testing.
  • Why store sessions on the server instead of in a JWT? Server-side sessions let you revoke access, support real 'remember me' behavior and prevent attackers from forging or replaying tokens against your API directly.
  • Which AI coding tool should I use for my team? It depends on your policies and workflow. The 2026 live benchmark showed Cursor writing the most pattern-consistent code, Claude 4.6 inside Antigravity delivering most reliably, and autonomy and permission behavior varying sharply between tools.
  • Where can I study TDD and these deployment decisions in a structured way? Free Rocketseat lessons cover TDD with Java, Rails and Webflux. Community programs such as Crazystack, the Crazystack Typescript track and the Bootcamp do Dev Doido by Gustavo Dev Doido offer guided paths toward the same stack decisions.
  • What is the difference between a scaffold and a framework? A scaffold like Grove generates a starting project with decisions already made, while a framework like Nest or Next imposes structure on every project. The scaffold approach keeps you free to swap libraries later.

Turn your own live sessions into reference articles

This article exists because a two-hour live session about deploying a project to production contained decisions worth reading slowly: the architecture trade-offs, the TDD loop, the documentation stack and an honest AI comparison. That knowledge usually stays trapped in a video timeline, replayed at whichever minute someone remembers.

If you run lives, record tutorials or explain architecture on YouTube, Skala Blog turns that footage into a structured written article. Paste the video URL, let it transcribe the session, and generate a searchable version your audience can quote, skim and find. What the live chat heard once becomes documentation developers can return to.

Source video