Lessons from Apps That Failed
Architecture mistakes in Shopify apps compound over time. What seems like a reasonable shortcut during initial development becomes a crippling limitation at scale. This article covers the mistakes we see repeatedly and how to avoid them.
Ignoring Rate Limits
The most common and most damaging mistake.
How rate limits work
Shopify uses a leaky bucket algorithm. You have a bucket of API calls that depletes with each request and refills over time. Exceed the bucket and you get 429 errors.
What goes wrong
Apps that ignore rate limits:
- Fail during high-volume operations
- Create poor user experiences with timeouts
- Lose data when requests fail silently
- Cause cascading failures in dependent processes
Proper handling
- Read rate limit headers from every API response
- Implement exponential backoff on 429 errors
- Queue requests rather than firing simultaneously
- Design workflows to stay within limits
Polling Instead of Webhooks
Polling the API for changes wastes resources and creates latency.
The polling trap
Some developers poll endpoints every few minutes to check for new orders, product changes, or customer updates. This approach:
- Consumes API calls continuously
- Introduces latency between event and detection
- Scales poorly as data volume grows
- Creates unnecessary load on your infrastructure
Using webhooks properly
Webhooks deliver events in near real-time when they happen. Subscribe to relevant topics:
- orders/create for new orders
- products/update for product changes
- customers/create for new customers
Your app receives HTTP POST requests with event data. Process them asynchronously to avoid blocking.
Webhook reliability
Webhooks can fail. Implement:
- Idempotent processing (handle duplicate deliveries)
- Retry logic for temporary failures
- Monitoring for missed webhooks
- Reconciliation processes to catch gaps
Synchronous Operations
Blocking operations during request handling creates timeout risks.
The problem
When your app receives a webhook or admin action, processing everything synchronously means:
- Request times out if processing is slow
- User waits for operations to complete
- Failures affect the entire request
Async processing
Accept the request quickly, queue work for background processing:
- Acknowledge webhook receipt immediately
- Queue the actual processing for a background worker
- Return success to the caller
- Process the queue asynchronously
This pattern handles volume spikes and prevents timeouts.
Poor Data Modeling
How you store and relate data affects long-term maintainability.
Not separating concerns
Storing everything in one table or document creates query problems. Separate:
- Shop data from feature data
- Configuration from transaction logs
- User data from operational data
Missing indexes
Queries that were fast with 100 records become slow with 100,000. Index fields you query frequently:
- Shop ID (always)
- Created/updated timestamps
- Status fields used in filters
- Foreign keys for joins
Not planning for multi-tenancy
Public apps serve multiple shops. Every query needs shop scoping. Missing shop filters cause data leakage between merchants.
Inadequate Error Handling
Silent failures are worse than loud failures.
What happens without error handling
- Operations fail without notification
- Data becomes inconsistent
- Debugging is difficult without context
- Support tickets arrive without useful information
Proper error handling
- Catch and log all errors with context
- Alert on critical failures
- Implement retry for transient errors
- Provide meaningful error messages to users
- Track error rates as metrics
Hardcoding Configuration
Configuration buried in code is difficult to change.
What to externalize
- API endpoints and credentials
- Feature flags
- Thresholds and limits
- Third-party service configuration
Environment-based configuration
Use environment variables or configuration services. Different environments (development, staging, production) need different values without code changes.
Ignoring Security Basics
Security mistakes create liability and risk app suspension.
Common security issues
- Not validating webhook signatures
- Storing credentials in code repositories
- Missing HTTPS enforcement
- SQL injection vulnerabilities
- Cross-site scripting in admin interfaces
Security essentials
- Validate HMAC signatures on all webhooks
- Use secrets management for credentials
- Enforce HTTPS everywhere
- Use parameterized queries
- Sanitize user input
Not Planning for Updates
Shopify's platform evolves. Apps must keep up.
API versioning
Shopify versions its API and deprecates old versions. Apps using deprecated versions eventually break. Plan for:
- Regular API version upgrades
- Testing against new versions before they become mandatory
- Monitoring Shopify's changelog for breaking changes
Dependency maintenance
Libraries and frameworks also require updates. Security vulnerabilities in dependencies become your vulnerabilities. Maintain dependencies actively.
For app development best practices, see custom Shopify apps.
Working with LiftKit Digital
LiftKit Digital builds apps with proper architecture from the start. We avoid these common mistakes so you do not inherit technical debt.
To discuss your app project, get in touch.