
Welcome to "Did You Know?" - a series where we share practical tips, clever workarounds, and non-obvious solutions discovered in real production codebases. These aren't theoretical best practices - they're battle-tested patterns from actual projects.
The Problem: You have a Flutter app targeting both iOS and macOS. You'd expect to build them in one pipeline, but Codemagic doesn't allow selecting both platforms in a single workflow.
Did you know? The solution is to use custom codemagic.yaml files with separate workflows:
workflows:
ios-build:
name: iOS Build
instance_type: mac_mini_m2
environment:
xcode: latest
scripts:
- flutter build ios --release
artifacts:
- build/ios/ipa/*.ipa
macos-build:
name: macOS Build
instance_type: mac_mini_m2
environment:
xcode: latest
scripts:
- flutter build macos --release
artifacts:
- build/macos/**/*.app
You can trigger both workflows in parallel from your CI, or chain them sequentially. The key insight: don't fight the UI limitations - embrace YAML-based configuration for full control.
The Problem: Every Docker build reinstalls all dependencies from scratch, even if nothing changed.
Did you know? BuildKit cache mounts persist pip and poetry caches across builds:
RUN --mount=type=cache,mode=0755,target=/root/.cache/pip pip install poetry==1.8.4
RUN --mount=type=cache,mode=0755,target=/root/.cache/pypoetry poetry install --no-root
This reuses downloaded packages across builds. A typical Python project with 100+ dependencies goes from 3 minutes to 30 seconds on subsequent builds.
The Problem: You need different startup commands for development (hot reload) vs production (gunicorn), but don't want to maintain separate Dockerfiles.
Did you know? You can switch behavior at runtime using environment variables in your command:
command: >
sh -c "if [ \"$DEVELOPMENT_MODE\" = \"True\" ]; then
poetry run python manage.py runserver 0.0.0.0:8000;
else
gunicorn --bind :8000 --workers 8 streamdatalab.wsgi:application;
fi"
Same image, different modes. Deploy once, configure per environment.
The Problem: Your app crashes on startup because the database isn't ready yet, even though you used depends_on.
Did you know? depends_on only waits for the container to start, not for the service to be ready. Use health checks:
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
# In the db service:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myuser"]
interval: 2s
timeout: 2s
retries: 10
Now Docker waits until PostgreSQL actually accepts connections.
The Problem: Your Celery workers slowly consume more memory until they get OOM-killed, taking running tasks with them.
Did you know? Celery has a built-in flag to gracefully restart workers that exceed a memory threshold:
command: celery -A myapp worker --loglevel=info --concurrency=4 --max-memory-per-child=100000
Workers restart themselves after processing tasks if they exceed ~100MB. Memory leaks become a minor nuisance instead of a production incident.
The Problem: Your static assets (images, fonts, JS bundles) get re-downloaded on every visit, wasting bandwidth and slowing load times.
Did you know? If your assets have hashed filenames (like app.a1b2c3.js), you can cache them forever:
{
"headers": [
{
"source": "**/*.@(jpg|jpeg|gif|png|svg|webp|ico|avif)",
"headers": [{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}]
}
]
}
One year cache, marked immutable. Browsers won't even send conditional requests. Combined with Nuxt or Next.js hash-based filenames, cache invalidation happens automatically on deploy.
The Problem: Your git history is a mess of "fix", "update", and "wip" messages. You want semantic versioning but can't parse the commits.
Did you know? You can reject non-conventional commits before they're even created:
# .pre-commit-config.yaml
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.0.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
Now git commit -m "fixed stuff" fails, but git commit -m "fix: resolve login timeout issue" succeeds. Your changelog writes itself.
The Problem: Your startup script fails midway through because a required Python module is missing, leaving the system in a partial state.
Did you know? You can validate critical imports before starting:
#!/usr/bin/env sh
set -eu
# Fail-fast import check
python - <<'PY'
import importlib
for m in ("fastapi", "uvicorn", "sqlalchemy"):
importlib.import_module(m)
PY
exec python -m uvicorn app.main:app --host 0.0.0.0 --port "$PORT"
If any import fails, the script exits immediately with a clear error. No partial startups.
The Problem: You're using Nuxt's static generation but have to manually list every route for prerendering.
Did you know? Nuxt can automatically discover pages by following internal links:
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
preset: 'static',
prerender: {
routes: ['/'],
crawlLinks: true // Magic happens here
}
}
})
Start from /, and Nuxt will find and prerender every linked page. Add new content, link to it from anywhere, and it's automatically included in the build.
The Problem: Your containerized app ignores the AWS credentials you set in environment variables and tries to use EC2 metadata (which doesn't exist outside EC2).
Did you know? You can explicitly disable the metadata service:
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- AWS_EC2_METADATA_DISABLED=true
- AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=
The AWS SDK has a credential chain that checks metadata before environment variables. Disabling metadata forces it to use your explicit credentials.
Did you know? You can be strict in production code but lenient in tests:
# ruff.toml
[lint.per-file-ignores]
"__init__.py" = ["E402"] # Allow late imports in init files
"**/tests/*" = ["E402", "S101"] # Allow assert statements in tests
"**/migrations/*" = ["E501"] # Allow long lines in migrations
No more disabling rules globally just because they don't apply everywhere.
This is Part 1 of an ongoing series. Each installment will bring 10 new tips from real codebases - no fluff, just practical knowledge.
Got a tip of your own? Found something clever in a codebase you're working on? Let us know - we might feature it in a future edition.
MusicTech Lab specializes in building software for the music industry. We've seen a lot of codebases. Contact us if you're building something interesting.
Building something similar or facing technical challenges? We've been there.
Let's talk — no sales pitch, just honest engineering advice.
Dev Meeting 001: Kubernetes is a Framework
What is Kubernetes, Google problems with scale, Alpha and then Borg to the rescue, How Kubernetes was born, Kubernetes basics are basics, Idea of Operators, CRD, Kubernetes basics in new light, Threat
Did You Know? 10 MusicTech Facts That Will Surprise You
A collection of fascinating facts about music technology, standards, and innovations that shape how we create, share, and experience music. Part 2 of an ongoing series.