Vinicius Aguiar
Carrera

En algún momento, escribir código deja de ser la parte difícil

23 de sept. de 2026 · 10 min de lectura

Durante mucho tiempo medí mi evolución por lo que era capaz de construir. Un framework nuevo aprendido, un tipo nuevo de app entregada, una línea más en la sección de stack del currículum. Parecía el marcador correcto, porque al principio casi lo era.

Lo que no noté fue el momento en que el marcador dejó de reflejar el juego. El código no se volvió exactamente más fácil. Solo dejó de ser la parte que me quitaba el sueño. Lo difícil se había movido a otro lugar: decidir qué construir, decidir qué no construir y convivir con las consecuencias de ambas cosas.

Este post es un intento de describir ese cambio tal como lo viví. No es un método para decidir quién es senior. Los títulos significan cosas distintas en empresas distintas y en mercados distintos. En 2025 fui Software Engineer en una empresa y Senior Software Engineer en otra, al mismo tiempo, y unos meses después Full Stack Developer en una tercera. El trabajo detrás de esos títulos era mucho menos distinto que las palabras. Así que léelo como la mirada de un ingeniero sobre cómo cambiaron los problemas, no como una escalera que todos tienen que subir.

Junior: aprender a ejecutar

Empecé en 2022, prototipando una app de delivery, web y mobile, mientras todavía estaba en la facultad. Estaba solo en ella, lo que significaba que tomaba todas las decisiones: la arquitectura, el modelo de datos, cómo se comunicaban las piezas. Durante un tiempo lo tomé como una señal de que estaba más avanzado de lo que realmente estaba.

Me llevó años entender la diferencia. Tomar decisiones que nadie revisa no es lo mismo que tomar buenas decisiones. Nadie me decía que una elección estaba mal, así que asumía que no lo estaba. Tomaba decisiones de arquitectura sin saber cuáles eran las alternativas, cuánto costaban o qué se iba a romper seis meses después. No sabía lo que no sabía.

Cuando entré a un equipo en 2024, trabajando en apps web y mobile con React, Next.js, React Native y Flutter, la forma de mi trabajo se volvió más clara y, siendo honesto, más cómoda. Las tareas llegaban bien definidas. Alguien ya había decidido qué debía hacer la pantalla; mi trabajo era hacer que lo hiciera. La pregunta que me hacía todo el día era:

"¿Cómo implemento esto?"

No es una pregunta pequeña. En esa etapa es la pregunta correcta. Estás aprendiendo el stack, el código, las convenciones que nadie escribió y la diferencia entre código que funciona en tu máquina y código que sobrevive al review. Necesitaba orientación a menudo, y necesitaba que fuera específica.

Mirando hacia atrás, lo principal que estaba construyendo no eran features. Era ejecución: la capacidad de tomar algo definido y convertirlo en software que funciona, sin drama. Todo lo que vino después depende de eso. No se puede razonar sobre trade-offs en un código que todavía cuesta escribir.

Mid-level: aprender a hacerse cargo

El paso a mid-level no llegó con un tipo nuevo de tarea. Llegó con menos instrucciones acompañando el mismo tipo de tarea.

En lugar de "construye esta pantalla", pasó a ser "necesitamos esta integración". Trabajé en integraciones con Mercado Livre, Shopee y Meta, y me hice cargo de publicar y mantener apps iOS a través de Apple Developer: el ciclo de release, las pautas de revisión de la App Store, la parte del trabajo que empieza después de que el pull request se mergea. Esa última parte me enseñó algo que el código nunca me enseñó. Una feature no está terminada cuando funciona. Está terminada cuando está en manos de los usuarios y sigue funcionando.

Los sistemas externos te obligan a aprender eso. Sus APIs dan timeout, cambian sin aviso, envían el mismo evento dos veces o responden con éxito con la mitad de los datos faltando. Así que las preguntas que me hacía empezaron a cambiar. ¿Qué pasa cuando esta llamada falla? ¿Y si este webhook llega dos veces? ¿Cómo pruebo esto sin cobrar una tarjeta real? ¿Cómo voy a saber que se rompió en producción antes de que un cliente me lo diga?

La pregunta debajo de todas ellas era:

"¿Cuál es la mejor forma de resolver esto?"

Esa pregunta asume que el problema ya es el correcto. Otra persona decidió qué estamos resolviendo; yo decido cómo. Pasé a ser responsable de edge cases, tests, performance y deploys, y necesitaba cada vez menos detalle en el ticket para entregar.

Es un paso real, y durante un tiempo parece que es todo el trabajo. Confían en ti. Entregas. La gente deja de revisar cada línea. Es fácil creer que el siguiente paso es solo más de lo mismo: features más grandes, sistemas más complejos, más tecnologías.

Para mí no lo fue.

Senior: aprender a decidir

La señal más clara de que mi trabajo había cambiado fue que empecé a recibir problemas en lugar de tareas.

No "construye X", sino "esta pantalla está lenta", "este sistema tiene que salir de Firestore", "los clientes no pueden pagar y no sabemos por qué". Sin especificación, a veces sin un responsable claro, y muchas veces con información incompleta sobre lo que realmente estaba pasando.

Nuevos problemas

Los problemas mismos cambiaron de forma. Pasaron a ser menos sobre una feature y más sobre un sistema que ya estaba funcionando, con gente que dependía de él.

Un ERP enfocado en la gestión de flotas en el que trabajé tenía que migrar su core de Firestore a PostgreSQL, y seis productos separados tenían que consolidarse en un único deploy multi-tenant. La restricción que definió todo fue que la operación no podía detenerse. Escribir el schema nuevo no era la parte difícil. Lo difícil era decidir cómo migrar módulo a módulo, qué podía coexistir y por cuánto tiempo, y qué riesgo estábamos dispuestos a aceptar en cada etapa. Nada de eso cabe en un ticket.

Nuevas responsabilidades

Las responsabilidades también cambiaron, y fueron más difíciles de notar, porque nadie te las entrega en un ticket.

  • Lo que pasa después del deploy. En un producto web y mobile usado por miles de personas, ser responsable significó crash reporting, logs y métricas: saber que algo se rompió antes de que un cliente te lo diga.
  • El dinero y los datos de otros. Pagos y webhooks, donde el mismo evento puede llegar dos veces y un retry descuidado le cobra a alguien de nuevo. Y decidir qué no recolectar: en un flujo de pago, lo que dejamos fuera de la instrumentación importó tanto como lo que capturamos.
  • Traducir trade-offs. Explicar a quien no lee código a qué estamos renunciando, por qué y cuánto va a costar después.
  • Construir menos. Cuestionar si la feature pedida resuelve el problema, y a veces argumentar en contra de construirla.
  • Hacerse cargo de la decisión. Decidir sin que alguien valide cada paso, y hacerse cargo cuando resulta equivocada.

Construir un producto desde cero otra vez fue lo que me hizo evidente la diferencia. En 2022, solo con la app de delivery, tomaba todas las decisiones y nadie pagaba por ninguna. Construyendo desde cero una plataforma multi-tenant de automatización de marketplace, con integraciones, pagos y flujos de pedidos, volví a tomar la mayoría de las decisiones. La autonomía era la misma. El peso era completamente otro: del otro lado de cada decisión había clientes pagando.

Así que la pregunta cambió otra vez:

"¿Qué problema estamos intentando resolver realmente?"

Esa pregunta es incómoda. A veces la respuesta es que la feature que alguien pidió no resuelve el problema que tiene. A veces es "todavía no lo sé, y así es como lo averiguamos". De una forma u otra, ahora la respuesta me toca a mí.

Seguro, y estancado

Hay una parte de esta etapa que no esperaba. Cuanto más crecía, más seguro me sentía. Y, al mismo tiempo, más estancado. Podía entregar. Conocía bien el stack, los sistemas, la producción. Esa seguridad servía para tomar decisiones, pero era pésima para mostrarme dónde había dejado de crecer.

Lo que me hizo avanzar otra vez no fue una tecnología nueva. Fueron personas. Empecé a recibir más ayuda de devs con más experiencia: staff engineers, managers, seniors, personas que tenían de experiencia los años que yo tengo de edad. Eso me enseñó muchísimo, y casi nada tenía que ver con sintaxis. Buena parte de lo que describí arriba, las preguntas que hago antes de escribir cualquier cosa, lo aprendí viendo cómo trabajaban.

La otra dirección me sorprendió más. Ayudar a personas que están empezando su carrera también me ayudó a mí. Explicar algo es la forma más rápida de descubrir si realmente lo entiendes, y responder las dudas de otra persona te obliga a ordenar lo que sabes. Eso moldeó cómo estudio, cómo aplico lo que aprendo y cómo transmito el conocimiento.

Creo que esa es la parte de la seniority que no cabe en un currículum: aprender de quienes van por delante mientras ayudas a quienes están empezando, al mismo tiempo.

El problema cambia

Si tuviera que resumir todo el cambio en una frase, sería esta: el código sigue siendo difícil, pero deja de ser el cuello de botella.

Lo que pasa a ser difícil:

  • Descubrir qué hay que construir realmente. Los requisitos llegan incompletos, y la parte que falta suele ser la importante.
  • Elegir trade-offs. Toda opción cuesta algo. El trabajo es saber qué, y decirlo en voz alta.
  • Trabajar dentro de sistemas existentes. La mayor parte del trabajo real no es greenfield. Es cambiar algo de lo que la gente depende mientras lo está usando.
  • Prever consecuencias. El schema que eliges hoy decide qué será barato y qué será doloroso durante los próximos dos años.
  • Trabajar con incertidumbre. Decidir con el 60% de la información porque esperar el 100% cuesta más.
  • Equilibrar velocidad y calidad. No como eslogan. Como una elección concreta, en una feature específica, esta semana.
  • Entender el impacto. Un error de frontend en el checkout no es un bug de UI. Es ingreso perdido que ningún dashboard técnico muestra.

Nada de esto reemplaza al código. Se apoya sobre él. Todavía hay que escribir la query, el componente, la migration. Pero la hora más difícil de la semana rara vez pasa en el editor.

El mercado lo nota

Me llevó un tiempo ver que el mercado seguía el mismo cambio, solo que con retraso.

Al principio, la forma en que te evalúan es casi toda legible en un currículum: qué tecnologías conoces, qué frameworks, qué proyectos construiste, cuántos años de experiencia tienes, si puedes implementar una feature. Tiene sentido. En esa etapa, esas son realmente las mejores señales de que puedes ejecutar.

A medida que crece el alcance, esas señales dejan de ser suficientes. Lo que empieza a importar es más difícil de enumerar:

  • ownership: si las cosas que tocas llegan a terminarse, incluida la parte después del deploy
  • autonomía: cuánta dirección necesitas para hacer avanzar un problema
  • toma de decisiones, y si puedes explicar las decisiones que tomaste
  • arquitectura, no como diagramas sino como consecuencias
  • impacto en el producto, no solo volumen de entrega
  • comunicación, sobre todo acerca de trade-offs y riesgo
  • comodidad con la ambigüedad
  • la capacidad de conectar una elección técnica con lo que el negocio intenta lograr

Lo que cambia no es solo cómo te evalúan. Es el tipo de oportunidad que aparece. Las tareas acotadas se convierten en problemas abiertos. "¿Puedes construir esto?" se convierte en "¿puedes descubrir qué deberíamos hacer aquí?". La confianza es otra, y la responsabilidad que viene con ella también.

Quiero tener cuidado aquí. Esto no es una promesa de salario ni un camino de carrera garantizado. Los mercados cambian, las empresas cambian, y mucha gente es subestimada o sobreestimada por razones que no tienen nada que ver con todo esto. Es solo lo que he notado: el valor percibido tiende a seguir el tamaño de los problemas que te confían, más que el largo de tu lista de stack.

Lo que cambió para mí

Si comparas mi stack de 2022 con la de hoy, creció. Pero no es eso lo que cambió. Podría listar todas las tecnologías que usé y no explicaría la diferencia entre cómo trabajaba entonces y cómo trabajo ahora.

Lo que cambió es por dónde empiezo. Antes empezaba por la implementación. Ahora empiezo por el problema, y trato de desconfiar de él antes de confiar. Pregunto qué pasa después del deploy, quién se entera cuando se rompe y a qué estamos renunciando. Dejé de tratar "nadie se opuso" como "estaba bien".

También cambié lo que considero terminado. Terminado significaba mergeado. Después significó en producción. Ahora significa que el problema está realmente resuelto, y que puedo explicar por qué esta solución y no otra.

Y casi nada de eso lo descubrí solo. Vino de personas que ya habían pasado por ahí antes que yo, y de tener que explicárselo a quienes todavía no.

Todavía estoy aprendiendo

No creo haber llegado a ningún lado. Hay cosas en las que todavía estoy trabajando: saber cuándo lo suficientemente bueno realmente es suficiente, distinguir un trade-off de un atajo, y decir "me equivoqué" más rápido que antes. Y sigo aprendiendo de la misma forma en que aprendí casi todo: de quienes van más adelante, y explicándoselo a quienes están empezando.

Y estoy casi seguro de que parte de lo que creo hoy me va a parecer ingenuo dentro de unos años, igual que mis primeras decisiones de arquitectura me lo parecen ahora. Está bien. Creo que de eso se trata.

El código va a seguir siendo parte del trabajo. Todavía lo disfruto, y desconfío de los ingenieros que dejan de preocuparse por él. Pero en algún momento, escribir código deja de ser la parte difícil. La parte difícil es todo lo que lo rodea: entender el problema, elegir a qué renunciar y hacerse cargo del resultado.

Esa es la parte que todavía estoy aprendiendo.