System overview
GOV.UK Notify Admin is the frontend administration interface for the GOV.UK Notify platform. Built with Flask and Python, it provides a secure web application for managing notification services, users, templates, and batch sending operations.Core components
The platform is architected as a modern Python web application with clear separation of concerns:Application layer
Flask web framework- Python 3.13 runtime environment
- Flask application factory pattern for flexible initialization
- Three blueprint architecture for request handling:
main_blueprint- Primary application routesjson_updates_blueprint- AJAX endpoints for real-time updatesstatus_blueprint- Health check and status endpointsno_cookie_blueprint- Cookie-free routes for embedded content
- Custom
NotifyAdminSessionInterfacefor secure session handling - 20-hour permanent session lifetime for standard users
- 30-minute inactive timeout for platform administrators
- Redis-backed session storage with configurable TTL
- Session refresh disabled by default except for specific endpoints
- Flask-Login for user session management
- Multi-factor authentication with three methods:
- Email 2FA (30-minute code expiry)
- SMS 2FA via user mobile number
- WebAuthn support for hardware keys and biometrics
- Custom
AnonymousUserclass for unauthenticated contexts - Permission-based access control with decorators:
@user_has_permissions()- Checks user service permissions@user_is_platform_admin- Restricts to platform administrators@service_has_permission()- Validates service capabilities
Data layer
API clients The admin application communicates with backend services via RESTful API clients:service_api_client- Service CRUD and configurationuser_api_client- User management and authenticationtemplate_folder_api_client- Template organizationnotification_api_client- Notification sending and trackingjob_api_client- Batch job managementbilling_api_client- Usage tracking and cost calculationorganisations_client- Organization managementinvite_api_client- User invitation workflowapi_key_api_client- API key generation and managementtemplate_statistics_client- Analytics and reportingevents_api_client- Audit logging
- Bearer token authentication via
ADMIN_CLIENT_SECRET - Automatic retry logic for transient failures
- Request/response logging for debugging
- Error handling with
HTTPErrorexceptions
- Session storage with automatic expiry
- Search query caching (7-day TTL for notification searches)
- Memo resetters for cache invalidation
- Optional Redis usage controlled by
REDIS_ENABLEDflag - Local development fallback when Redis unavailable
Storage layer
Amazon S3 buckets Multiple S3 buckets handle different file types:S3_BUCKET_CSV_UPLOAD- Batch upload CSV files with metadataS3_BUCKET_CONTACT_LIST_UPLOAD- Reusable contact listsS3_BUCKET_LOGO_UPLOAD- Email and letter branding logosS3_BUCKET_TRANSIENT_UPLOADED_LETTERS- Temporary letter PDFsS3_BUCKET_PRECOMPILED_ORIGINALS_BACKUP_LETTERS- Letter backupsS3_BUCKET_LETTER_ATTACHMENTS- Letter attachment filesS3_BUCKET_TEMPLATE_EMAIL_FILES- Email template attachmentsS3_BUCKET_REPORT_REQUESTS_DOWNLOAD- Generated CSV reportsS3_BUCKET_MOU- Memorandum of Understanding documents
- Logo files served via
LOGO_CDN_DOMAINfor performance - Static assets served from
ASSET_DOMAINwith fingerprinting - DNS prefetch and preconnect headers for optimized loading
External integrations
Template preview serviceTEMPLATE_PREVIEW_API_HOST- Renders email and letter previews- Generates PNG previews for letters
- PDF page counting for postage calculation
- Real-time template rendering with test data
ANTIVIRUS_API_HOST- Scans uploaded files for malware- Validates CSV uploads and letter PDFs
- Blocks malicious content before processing
- Optional in development, required in production
ZENDESK_API_KEY- Support ticket creation- Feedback form submission to Zendesk
- Automatic ticket categorization with subject prefixes
Request lifecycle
Understanding how requests flow through the system:Request initiation
User navigates to a route, triggering Flask’s routing system:Custom URL converters handle specialized types:
uuid- Service and organization IDs (auto-lowercased)template_type- Email, SMS, or letter validationagreement_type- MOU agreement typesbase64_uuid- Encoded identifiers
Before request hooks
Multiple hooks execute before the view function:
make_nonce_before_request()- Generates CSP nonce for inline scriptsload_user_id_before_request()- Extracts user ID from sessionload_service_before_request()- Loadscurrent_servicefrom URL or sessionload_organisation_before_request()- Loadscurrent_organisationfrom URLrecord_start_time()- Timestamps request for metrics
g object with request-scoped data:Authentication check
Flask-Login verifies user authentication:
- Checks session for
user_id - Loads
Userobject viaload_user()callback - Sets
current_userproxy for template access - Redirects to sign-in if unauthenticated and required
Permission validation
View decorators verify user permissions:Permission types include:
manage_users- Invite and manage team membersmanage_templates- Create and edit templatesmanage_settings- Configure service settingssend_messages- Send notificationsmanage_api_keys- Generate API keysview_activity- Access dashboard and reports
View execution
The route handler processes the request:
- Fetches data from API clients
- Processes form submissions
- Performs business logic
- Returns template rendering or redirect
Response processing
After request hooks apply security headers:
X-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINContent-Security-Policywith nonce-based inline script allowanceStrict-Transport-Securitywith 1-year max-ageCache-Control: no-storefor sensitive data- Custom
Serverheader for obfuscation
Security architecture
Multiple layers protect user data and prevent attacks:Transport security
- HTTPS enforced in production via
HTTP_PROTOCOLandSESSION_COOKIE_SECURE - HSTS headers with
includeSubDomainsandpreloaddirectives - TLS certificate validation for API calls
Application security
CSRF protection- Flask-WTF CSRF tokens on all forms
- Automatic validation on POST requests
- No time limit on CSRF tokens (
WTF_CSRF_TIME_LIMIT = None) - Session-tied tokens prevent reuse across sessions
- WTForms for declarative form validation
- Email address format validation
- UK phone number validation with international support
- Postal address validation for letters
- File upload validation (size, type, content)
- CSV structure validation with error reporting
Session security
- Secure cookie flags (
httponly,secure,samesite=Lax) - Session data stored server-side in Redis
- Session IDs never exposed in URLs
- Automatic session expiry based on inactivity
- Platform admin sessions expire faster (30 minutes)
File upload security
- Antivirus scanning before processing
- File type validation (CSV, PDF, PNG, JPG)
- File size limits enforced
- S3 bucket access restricted via IAM
- Temporary file cleanup after processing
Performance optimizations
Frontend performance
Asset management- Asset fingerprinting for cache busting
- CDN delivery for static files and logos
- Rollup for JavaScript bundling
- CSS and JavaScript minification
- Font subsetting with WOFF2 compression
- DNS prefetch and preconnect for external resources
- Server-side rendering for initial page load
- AJAX updates for dynamic content (dashboard statistics, notification lists)
- Lazy loading for dashboard partials
- JSON update endpoints for polling:
Backend performance
Caching strategies- Redis caching for search queries (7-day TTL)
- Memoization for expensive computations
- Service and organization data cached in
gobject per request - Asset fingerprint caching across requests
- Pagination for large result sets (50 notifications per page)
- Lazy loading of related objects
- Efficient filtering at API level
- Aggregated statistics instead of individual queries
- Eventlet for async I/O in production
- Parallel API calls where possible
- Background job processing for batch operations
- Non-blocking file uploads to S3
Deployment architecture
Environment configuration
Three environment tiers with distinct configurations: DevelopmentLogging and monitoring
Request logging- GDS Metrics integration for performance tracking
- Request start time recording via
g.start - Error logging with structured context
- API call logging with URL and status code
400- Client errors logged as exceptions401/403- Authentication/authorization failures404- Not found with service-specific templates410- Gone resources500- Internal errors with stack traces in debug mode504- Eventlet timeout handlingHTTPError- API client errors with response detailsCSRFError- CSRF validation failures with session checks
- Status blueprint for uptime monitoring
- Unauthenticated, unstyled, no-cookie status page
- Integration with platform health checks
Data models
Key domain models mirror API responses: Service modelDevelopment workflow
Local setup
Project structure
Next steps
Getting started
Set up your first service and send notifications
API reference
Integrate with the GOV.UK Notify API