Context
Viya Wallet was a super-app modeled after WeChat, combining wallet functionality with integrated chat features. The system consisted of a Go backend with custom authentication and a Flutter frontend designed for bilingual operation (English and Dhivehi). The project aimed for production deployment but encountered significant technical and organizational challenges.
To see how I personally handled the failure, refer to On Handling Failure.
System Architecture
Backend
Authentication system: Custom implementation in Go using JWT-based authentication with role-based access control (RBAC). Security-critical components required extensive penetration testing covering rate limiting, encryption, JWT validation, session management, RBAC enforcement, and authentication flows.
Session management: Persistent session storage with expiration, invalidation, and revocation mechanisms.
Core services: Wallet operations, transaction management, and chat functionality as integrated backend services.
Data layer: PostgreSQL managed via shell-based psql sessions.
Infrastructure: Go application deployed via GitHub Actions to a self-hosted free-tier EC2 instance. Nginx as reverse proxy, Docker Compose for orchestration with systemd as fallback. Infrastructure defined as code; AWS security groups and firewall rules configured for network security.
Frontend
Framework: Flutter for cross-platform mobile development.
Internationalization: All user-facing text stored in constants files. English implementation completed; Dhivehi (RTL) support designed but not implemented.
Architecture: Single codebase targeting both language configurations through compile-time constants.
Development Context
Team Structure
Individual contributors handled multiple domains simultaneously: backend development, security validation, frontend implementation, infrastructure operations, database management, network configuration, and deployment automation. This created constant context switching across security engineering, UI development, infrastructure operations, database administration, and feature implementation.
Scope Characteristics
Super-app architecture creates compounding complexity. Custom authentication alone requires security expertise and extensive testing. Chat, wallet operations, bilingual support, and mobile deployment each represent significant independent engineering efforts. Combined, they represent substantial scope for a small team.
Technical Challenges
Authentication and Authorization
Custom authentication required JWT token generation, validation, and refresh; role-based access control; session persistence and invalidation; threat modeling; and sustained penetration testing across multiple attack vectors. This consumed significant development time but was necessary given the financial nature of wallet operations.
Infrastructure Limitations
Free-tier EC2 created resource constraints that were underestimated during planning: insufficient storage for Docker images and logs, CPU contention during builds, memory pressure under normal operation, and I/O bottlenecks during deployment.
Deployment Complexity
The GitHub Actions and Docker Compose workflow encountered repeated failures from storage exhaustion, build timeouts, container startup failures, and log accumulation. Systemd proved more stable as a fallback but eliminated deployment consistency. The chosen strategy required more robust infrastructure than was available.
Integration Surface Area
Multiple stacks and operational layers created significant coordination overhead: Go backend and Flutter frontend with separate build processes; JWT and RBAC needing validation across client and server; Nginx, AWS security groups, systemd, psql, and SSH-based administration all requiring separate expertise and maintenance. Each layer added complexity and potential failure modes.
Testing Strategy
Security testing validated RBAC enforcement, JWT token handling, session management, rate limiting, and authentication flows. Application testing included unit tests for Go and wallet logic, integration tests for API endpoints and database operations, and manual testing via USB debugging. Infrastructure testing covered Docker Compose deployment, EC2 resource constraints, GitHub Actions reliability, systemd fallback, and postmortem review.
Planning Analysis
Scope vs Capacity
The project scope exceeded available engineering capacity on multiple fronts. Custom authentication with JWT, RBAC, and penetration testing required sustained security focus. Chat and wallet features each represented full-product efforts. Flutter, Go, and infrastructure work required different skill sets. Operational burden across databases, networking, service management, and deployment automation competed directly with feature development.
Several architectural decisions compounded this: custom auth rather than existing solutions, real-time chat alongside wallet functionality, bilingual infrastructure from the start, full CI/CD automation before manual deployment was validated, and container orchestration on constrained infrastructure. Each decision was individually justifiable but collectively exceeded available capacity.
Infrastructure Assumptions
Deployment architecture assumed resources free-tier EC2 could not provide. Docker Compose overhead was not validated against EC2 capacity; storage growth from builds and logs was not projected; CI/CD resource usage was not profiled before implementation. There was no contingency for resource constraints.
Organizational Factors
The project lacked formal project management structures that might have identified resource constraints earlier, prioritized features against capacity, established realistic timelines for security work, and created clear success criteria. Without these structures, scope naturally expanded rather than being constrained by delivery objectives.
Small team size meant informal coordination, which created issues when security decisions had cross-cutting implications, technical choices affected multiple work streams, or deployment failures blocked other work.
Technical Insights
On custom security implementations: JWT, RBAC, and session management require substantial security engineering investment. Unless core to product differentiation, existing solutions should be strongly preferred, with security testing factored explicitly into timelines.
On super-app scope: Combining wallet, chat, authentication, and mobile features represents multiple complete products. This scope requires significant team size or substantially longer timelines than single-purpose applications.
On infrastructure validation: Deployment architecture must be validated against actual resources before development begins. Container orchestration overhead must be measured, not assumed. Free-tier constraints eliminate certain technical approaches entirely.
On internationalization timing: RTL support affects fundamental layout decisions. Deferring it defers non-trivial complexity.
On operational burden: Managing infrastructure, security, databases, and networking competes directly with feature development. This operational tax must be accounted for in capacity planning.
Future Approach
Scope definition: Feature sets aligned with available engineering capacity. Security implementation time budgeted explicitly. Super-app scope reserved for appropriately-sized teams.
Authentication strategy: Existing solutions preferred unless the security model requires custom implementation. JWT, RBAC, and session management complexity factored into planning.
Infrastructure first: Deployment environment validated before architectural decisions. Automation introduced after manual deployment is proven stable.
Technology consolidation: Framework choices minimized to reduce coordination overhead and allow deeper expertise in fewer tools.
Process structure: Formal project management introduced regardless of team size, with regular scope review and testing integrated into timelines.
Conclusion
Viya Wallet's scope exceeded available resources. Custom authentication, super-app features, security testing, bilingual support, and infrastructure constraints collectively created a development burden too large for the team size.
Each individual component was technically sound. The challenge was attempting to deliver all components simultaneously with limited engineering capacity and constrained infrastructure. The project validated that super-app architecture with production-grade security requires corresponding team size and infrastructure investment.
Future work will maintain technical ambition while ensuring scope aligns with capacity from project inception, with security requirements and infrastructure constraints validated through measurement rather than assumption.