# Container Pooling Implementation - Lessons Learned ## Original Problem User requested container pooling to improve performance by keeping containers ready instead of creating them on-demand for each request. ## What We Tried ### 1. Container Persistence Issues - **Problem**: Containers were exiting immediately after creation - **Root Cause**: Original `claudecode:latest` image was designed for single-command execution with `--rm` flag - **Solution**: Changed container creation to use `tail -f /dev/null` to keep containers alive - **Result**: ✅ Containers now stay running ### 2. Execution Model Mismatch - **Problem**: Pooled containers needed different execution approach than on-demand containers - **Original Clean Execution**: Single Docker run command with full entrypoint setup - **Pooled Execution Attempt**: Complex multi-step process: 1. Clone repository into running container 2. Set up environment 3. Execute Claude Code directly - **Issues**: - Broke the clean single-command execution model - Required complex command file handling - Made error handling more complex - Lost the simplicity of the original design ### 3. Architecture Conflicts - **Original Design**: Stateless containers that handle everything from scratch - **Pooled Design**: Stateful containers that need workspace management - **Conflict**: The execution logic became significantly more complex ## Key Insights 1. **Container Persistence**: Using `--entrypoint="/bin/bash" -c "echo 'ready'; exec tail -f /dev/null"` keeps containers alive 2. **Execution Complexity**: Pooled containers require fundamentally different execution logic 3. **Clean Design**: The original single Docker run command was elegant and reliable 4. **Workspace Management**: Pooled containers need careful workspace cleanup between uses ## Recommended Approach Instead of complex pooled execution, consider: 1. **Container Pre-warming**: Keep containers running but use the same execution model 2. **Simpler Pool Usage**: - Use pooled containers for faster startup - But execute using the same clean entrypoint approach - Pass the same environment variables and let the entrypoint handle setup 3. **Hybrid Approach**: - Keep the clean `docker run` execution model - But reuse container instances by removing `--rm` flag - Clean up containers after use rather than during creation ## Next Steps 1. Revert to original clean execution approach 2. Implement simpler pooling that doesn't change execution complexity 3. Focus on container reuse rather than execution model changes ## Code Locations - Container pool service: `src/services/containerPoolService.ts` - Execution logic: `src/services/claudeService.ts:170-210` - Container creation: Modified Docker command in pool service ## Performance Gains Observed - ✅ Container creation time reduced (containers stay alive) - ❌ Execution complexity increased significantly - ❌ Error handling became more complex - ❌ Lost single-command simplicity