EVE PHP Architecture and AWS Resources
Last updated: 10 September 2026
1. Purpose and agreed decisions
This document describes the implemented target deployment, not a claim that it has already been applied to production or load-tested. It records the agreed PHP-based direction; the earlier Node.js/React proposal in EVE_OPTIMIZED_ARCHITECTURE_SPECIFICATION.md is not the implementation target.
- Keep PHP, the Laravel/Livewire administrator interface and Flutter.
- Preserve mobile-number login without verification as an explicitly accepted business decision. A mobile number is not verified proof of identity; this does not relax administrator or publishing-service authorization.
- Run the student API and administrator application on the same application infrastructure.
- Normally run one application EC2 instance. Add capacity through an Auto Scaling Group (ASG) when measurements justify it.
- Run video/HLS conversion and exceptional oversized media jobs on separate, on-demand conversion compute.
- Process normal images, PDFs and audio with separate usage-based Lambda functions. The application EC2 performs no media compression.
- Reuse the existing
evequalityS3 bucket andhttps://evevideoquality.rayandmartin.inCDN for video, audio, PDFs and thumbnails; do not create a second media bucket or distribution. - Store new browser uploads temporarily below
incoming/. After verified publication and the configured retention period, delete only those temporary source objects. - Keep processed video in the existing EVE 2.0 board/class/subject/service/unit/chapter directory structure. Store relative S3 keys in the new media tables and construct delivery URLs from the configured CDN domain.
- Let the existing offline converter continue updating
video.transfer_pathandvideo.hls_status. Register validated HLS output in the new media tables without copying, moving or deleting its S3 objects. - Use one small, shared Grafana OSS EC2 instance to visualize CloudWatch data from EVE and the other approved Ray & Martin AWS projects.
- Collect student viewing analytics through controlled Flutter/PHP events and reporting tables; do not infer views from HLS segment requests.
- Create a new RDS database and migrate existing data safely.
- Preserve users, identifiers, media codes, existing QR links and old-app MP4 compatibility.
- Do not size around the earlier 50,000 concurrent viewers assumption: that number was a guess, not a measured requirement.
One application instance and Single-AZ RDS deliberately prioritize baseline cost over uninterrupted availability. Replacement and recovery can cause downtime.
2. Evidence used for planning
Existing CloudFront distribution observed during planning: E38VYWZ9U9RKXN. The new Terraform composition does not create, replace or modify this distribution.
| Period | Recorded downloaded data | Recorded requests | Data quality |
|---|---|---|---|
| June 2026 | 14.23 TB | 487,744 | 2 blank hourly entries |
| July 2026 | 19.35 TB | 500,299 | 7 blank hourly entries |
| August 30–September 6, 2026 export | 3.13 TB | 78,139 | 168 hourly entries, no blanks |
TB above uses decimal bytes. Exports use Sum with one-hour periods. Blank entries were not assumed to represent zero traffic. Requests and bandwidth do not identify concurrent viewers. MP4 request counts must not be reused unchanged to budget HLS segment requests.
Existing EC2 screenshots show low plotted CPU. RDS screenshots show low plotted CPU, considerable freeable memory and little disk queueing, but hourly aggregation can hide brief peaks.
Current RDS configuration supplied by the user:
db.r6i.large: 2 vCPU, 16 GiB RAM.- MySQL 8.0.45; Single-AZ; Mumbai.
- 200 GiB gp3; 3,000 IOPS; 125 MiB/s throughput.
- Storage autoscaling up to 1,000 GiB; encryption and deletion protection enabled.
- Database Insights Standard and Enhanced Monitoring at 60-second granularity.
Actual table sizes and growth have not been confirmed. The earlier approximately 9 GiB occupied-disk estimate came from a free-storage graph; it is not a measured table-size total.
3. Main architecture
The publisher is a logical responsibility, not an extra always-running server. Processor-side validation stays with the worker or Lambda that created the candidate. The application performs a bounded, authorized activation transaction after verification. A Lambda function is not an always-running server and has no provisioned concurrency in this design.
4. Resource inventory
All regional resources are proposed in Mumbai (ap-south-1). CloudFront is global; its CloudWatch metrics are viewed in us-east-1.
Application, conversion and data
| Resource | Quantity / specification | Operation |
|---|---|---|
| Application ASG | 1 group; minimum 1, desired 1; maximum pending load tests | Maintains app capacity and replaces unhealthy instances |
| Application EC2 | Candidate m8g.large: 2 vCPU, 8 GiB RAM, ARM64 | Normally one; PHP API and admin together |
| Application EBS | 40 GiB gp3 per app instance | OS, release artifacts and bounded temporary/log space; no permanent uploads |
| Application Load Balancer | 1 ALB, application target group, health checks | Routes traffic to healthy instances |
| Conversion ASG | 1 group; minimum 0, idle desired 0, maximum 1 | Launches capacity when work arrives |
| Conversion EC2 | Candidate c8g.2xlarge: 8 vCPU, 16 GiB RAM, ARM64 | PHP CLI jobs and FFmpeg, not HTTP serving |
| Conversion EBS | Temporary gp3; size based on maximum accepted source and output | 200 GiB was a budgeting example, not a confirmed requirement; use disk checks and delete-on-termination after durable storage |
| Image processor | 1 ARM64 Lambda container; initial 1 GiB memory, 1 GiB temporary storage | Sharp creates normalized responsive images and thumbnails; benchmark before final limits |
| PDF processor | 1 ARM64 Lambda container; initial 2 GiB memory, 2 GiB temporary storage | Ghostscript optimizes embedded images and qpdf validates/linearizes without rasterizing pages |
| Audio processor | 1 ARM64 Lambda container; initial 2 GiB memory, 2 GiB temporary storage | FFmpeg creates the approved AAC/M4A profile and any required legacy-compatible output |
| Launch templates | 2, one per ASG | Versioned machine image and bootstrap configuration |
| New RDS MySQL | Candidate db.m7g.large: 2 vCPU, 8 GiB RAM; Single-AZ | Private application database; validate on restored data before adoption |
| New RDS storage | Undecided until usage and growth are measured | 30–50 GiB is only a candidate; never allocate less than required data, indexes and operational headroom |
| Existing media S3 bucket | evequality; referenced rather than created by the new Terraform composition | incoming/ contains temporary new uploads; processed files use the existing EVE 2.0-style top-level folders |
| Existing CloudFront/CDN | https://evevideoquality.rayandmartin.in; no new distribution | Delivers both offline-converted and newly processed media through one compatible domain |
| Bucket CORS | Existing document is preserved by default | Terraform management remains disabled until the current rules are exported, reviewed and merged with direct-upload requirements |
| SQS queues | 1 Standard video/heavy-media queue + DLQ; separate image, PDF and audio queues + DLQs; 1 playback-analytics queue + DLQ | Isolated retries, timeouts, permissions and failed-job handling for each workload |
| Worker automation | CloudWatch queue alarms/scaling policy + scheduled EventBridge/Lambda reconciler | Starts workers and safely scales down idle capacity |
| Lightweight queue/dispatch process | Bounded supervised PHP process on app infrastructure where suitable | Reliable dispatch/reconciliation; never FFmpeg in the HTTP process |
| Shared Grafana EC2 | 1 t4g.micro: 2 burstable vCPU, 1 GiB RAM, ARM64 | Grafana OSS only; reads CloudWatch from EVE and other approved AWS projects |
| Grafana EBS | 10 GiB gp3 | Grafana configuration/SQLite data; back up configuration and database to restricted S3 |
ASGs are not extra servers. Normal compute is one app instance plus zero conversion instances. During video or exceptional heavy processing it becomes one app instance plus one worker, before any API scale-out. Merely defining the three Lambda functions does not create three continuously running servers.
A one-worker ceiling limits cost but can create conversion backlog. Set an acceptable conversion turnaround target and validate throughput against it. No separate admin EC2, Kubernetes, Redis or RabbitMQ is required by this design.
The shared t4g.micro is a strict cost-first Grafana starting point for a few operators and modest dashboards. It is not highly available. Run no Prometheus, Loki or image-rendering service on it. Use 1–5 minute dashboard refresh intervals, limit plugins and upgrade the instance only if measured memory or latency requires it.
ARM64 dependencies, PHP extensions, Sharp, Ghostscript, qpdf and FFmpeg must pass compatibility and performance tests. Use x86_64 for an individual processor only if a required dependency cannot be validated on ARM64. Exact supported runtimes are selected and pinned during implementation; do not copy an obsolete runtime merely to match the old server.
Networking, security and supporting resources
| Resource | Proposed configuration / responsibility |
|---|---|
| VPC | One application network, with subnets in at least two Availability Zones |
| Subnets | Public ALB subnets and private RDS subnets; EC2 outbound-network design explicitly documented |
| Security groups | Separate ALB, app, worker and database permissions; no public database access |
| Grafana access | HTTPS plus trusted-IP/VPN/SSM access; never expose Grafana port 3000 to the public internet |
| Outbound access | Cost-first option: tightly restricted EC2 with public IPv4, no public SSH, SSM management; private EC2 requires separately priced NAT/endpoints or another validated egress design |
| S3 gateway endpoint | Route worker/app S3 traffic without NAT processing |
| IAM roles | Separate least-privilege app, worker, per-processor Lambda, scaling and deployment roles; read-only cross-account CloudWatch roles for Grafana; no permanent AWS keys in source |
| Secrets | Standard Parameter Store for configuration; SecureString/Secrets Manager for secrets as appropriate |
| HTTPS and DNS | ACM certificates and existing DNS/QR domains; the media distribution remains existing infrastructure and the ALB certificate belongs in Mumbai |
| WAF | Protect public endpoints; a CloudFront media plan does not automatically protect a separately exposed ALB |
| Systems Manager | Managed instance access, deployment and operational commands |
| GitHub Actions + OIDC | Tested build artifacts and short-lived AWS deployment access |
| Terraform | Network, IAM, ASGs, Lambda processors, queues, reference to the existing media bucket/CDN, Grafana EC2, cross-account read roles, alarms and deployment configuration |
| Operational S3 storage | Separate restricted bucket(s), as needed, for Terraform state, release artifacts and audit logs; these are not additional media-delivery buckets |
| Backup policies | RDS automated backups and recovery tests; processed-version retention; bounded temporary-source, image and snapshot retention |
| CloudTrail | AWS control-plane audit history; not a replacement for host shell/session auditing |
5. How media processing works
Detailed database and AWS lifecycle references:
- Video upload and HLS database flow
- Audio upload and compression database flow
- PDF upload and optimization database flow
- Image and thumbnail upload database flow
Shared-bucket upload rule
The browser uploads every new source directly to evequality/incoming/... using a short-lived signed request. The application records the source in media_uploads; it does not proxy the file through PHP. Processors read that temporary object and write the verified result into the existing EVE-compatible directory space in the same bucket. IAM separates temporary-source permissions from the bounded list of permitted output prefixes.
The application deletes an incoming/ source only after the matching processed version is verified, published and active, and after the configured retention period (currently 24 hours). This cleanup never targets HLS registered from the offline converter. Bucket CORS is not taken over automatically because S3 has one complete CORS document per bucket.
Normal image, PDF and audio processing
The application validates upload metadata, records a durable job/outbox entry and dispatches only the job ID to the media-specific SQS queue. The corresponding Lambda downloads the approved incoming/ object, validates the real file signature and configured limits, creates a versioned candidate in the shared bucket, verifies the result and requests guarded activation. Each function has batch size one, reserved maximum concurrency initially set to one, no provisioned concurrency and bounded retries to its own DLQ.
For a video thumbnail, the primary compressed file is WebP and is written beside that video's HLS files as {video-directory}/thumbnail.webp; responsive/compatibility variants stay in the same directory. The relative key is stored in the thumbnail asset's media_versions.object_key, media_assets.active_version_id selects it, and publication updates legacy video.videoThumbnail with the full CDN URL. Audio publication similarly updates audio.audio or audio.audioThumbnail; PDF publication updates pdfSolutions.pdflink or pdfSolutions.pdflogo.
Initial configurations are hypotheses, not capacity guarantees: image 1 GiB memory/1 GiB temporary storage, PDF 2 GiB/2 GiB with a five-minute target, and audio 2 GiB/2 GiB with a ten-minute target. File-size, page-count, pixel-count, duration and runtime thresholds must be fixed from staging benchmarks. Jobs predicted or observed to exceed safe Lambda limits route idempotently to the video/heavy-media queue and existing conversion EC2; they never fall back to the application server.
Video and heavy-fallback worker
Required engineering safeguards:
- Queue depth is approximate; do not terminate based only on visible-message count.
- Use coordinated draining and durable job leases so a new job cannot race with idle shutdown. The reconciler must restore capacity if work arrives during scale-down.
- Protect busy instances from normal ASG scale-in; this does not prevent hardware failure or all termination causes.
- Renew SQS visibility while processing, respecting the service visibility limit. Set job runtime limits accordingly.
- Expect duplicate delivery. Make conversion attempts and publication idempotent, using stable job IDs and unique candidate version paths.
- Retry transient failures with limits; move repeated failures to the dead-letter queue and alert an operator.
- Recover expired job leases after a worker crash; never interpret a stale heartbeat as successful publication.
- Keep completed versions in S3. Keep new sources only in
incoming/until verified publication plus the configured retention period; local work space is disposable. - An empty queue does not mean a conversion has finished. Track in-flight work and application job state.
- On-demand here means launch and terminate, not permanently retain a stopped machine. Paid EC2 On-Demand purchasing is separate from this lifecycle concept; Spot is not assumed.
- A Lambda timeout or unsupported input must create an explicit, idempotent heavy-fallback job; it must not cause two processors to publish competing results.
6. Safe publication and old-app compatibility
New uploads
- A legacy catalogue row and its
media_assetsrecords identify the content and thumbnail independently. - Upload the original directly to
evequality/incoming/{type}/{asset}/revision-{n}/...with restricted temporary permission. - Confirm its size, MIME type, checksum and real file signature; then record the durable processing job and outbox message.
- Build the final prefix by mirroring a safe existing source hierarchy when available, otherwise from board/class, subject, service, unit, chapter and the permanent video name/code. This follows EVE 2.0 rather than introducing a new
published/hierarchy. - Video output contains
240p/,360p/,480p/,720p/as supported by source resolution, plusmaster.m3u8. The primary compressed thumbnail is{same-video-prefix}/thumbnail.webp. - Verify object existence, non-zero size and type-specific requirements: HLS inventory/manifests/codecs/duration; audio codec/duration; PDF structure/page count/selectable content; image decoding/dimensions/pixel limits.
- Store the relative final key in
media_versions.object_key, then atomically setmedia_assets.active_version_id. Prevent an older competing job from replacing a newer activation. - Write compatibility fields after publication: video HLS updates
video.transfer_pathandvideo.hls_status = ready; thumbnails updatevideo.videoThumbnail; audio and PDF fields receive their corresponding full CDN URLs. - Delete only the matching
incoming/original after verified publication and the configured retention period. Retain published versions for rollback according to policy.
The permanent media/QR code never changes. video.video remains the legacy source/MP4 reference during migration; the verified HLS master goes in video.transfer_path. The application constructs full delivery URLs from the configured CDN domain, while new media tables store portable relative S3 keys.
Existing offline-converted videos
The existing converter may continue uploading HLS to its current evequality directory and setting video.hls_status = ready plus a full CDN URL in video.transfer_path. The scheduled eve:import-legacy-hls command:
- accepts only configured CDN hosts and safe relative keys ending in
master.m3u8; - validates the master manifest, every referenced rendition playlist and every referenced segment in place;
- creates or updates the corresponding content
media_assetsrecord and a verifiedmedia_versionsrow; - stores the relative master key in
media_versions.object_keyand selects it throughmedia_assets.active_version_id; - skips a video with a modern active version or active processing job; and
- never uploads, copies, moves or deletes the offline converter's S3 objects.
Run php artisan eve:import-legacy-hls for a read-only preview before the first --execute run. The deployed scheduler processes bounded batches so conversion and migration can overlap safely.
The existing CloudFront/CDN origin policy must remain compatible with master playlists, variants and segments on real devices. This implementation does not assume or replace its current OAC/public-access configuration. Student access controls are a separate concern and must be verified without breaking old clients.
7. Monitoring and alerts
CloudWatch remains the operational data source and alarm/scaling system. One shared, self-hosted Grafana OSS EC2 provides dashboards across five approved AWS projects. Firebase covers Flutter crashes and mobile performance.
Grafana is only the visualization layer. It does not replace CloudWatch, store infrastructure logs or control scaling. CloudWatch alarms remain authoritative even when Grafana is unavailable. Do not install Prometheus, Loki or Grafana image rendering on the 1 GiB instance.
Product viewing analytics
Video popularity and student viewing reports are application data, not infrastructure metrics. They require explicit Flutter and PHP implementation:
Send events at meaningful points: playback requested, started, controlled progress intervals, player closed, completed and failed. Do not send an event every second. Define a valid view explicitly, for example only after a measured minimum playback duration. Store timestamps in UTC and display them in the required business timezone.
The reporting layer should calculate total views, unique viewers, watch duration, completion rate, repeat views, popular content, viewing time patterns and playback failures. Never use CloudFront request count as video-view count: HLS creates many playlist and segment requests for one viewing session. Do not use student IDs or video codes as CloudWatch metric labels; aggregate them in reporting tables instead.
| Area | Signals / tools | Important alarms |
|---|---|---|
| App EC2 | CloudWatch Agent: CPU, RAM, disk; instance status | Unhealthy instance, sustained resource pressure, disk exhaustion |
| ASG and ALB | Healthy targets, desired/actual capacity, scaling activity, requests, latency and errors | No healthy targets, failed launches, sustained latency/5xx rise |
| PHP-FPM/API | Structured logs and sampled OpenTelemetry; active/idle workers, request queue, slow requests, database spans | Worker saturation, growing request queue, error/latency regression |
| RDS | Database Insights Standard, Enhanced Monitoring and slow-query logging | Low memory/storage, connection pressure, slow queries, latency/IOPS pressure |
| SQS | Visible/in-flight messages, oldest-message age, DLQ | Old jobs waiting too long; any DLQ message requiring action |
| Conversion | Job heartbeat, elapsed time, disk headroom, source/output size, retry count | Stalled/failed conversion, repeated retries, worker never starts |
| Lambda media processors | Invocation errors, duration, throttles, concurrency, queue age, output ratio and fallback count | Timeout/throttle spike, repeated invalid files, stale queue or unexpected fallback growth |
| Publication | Verification results and active-version audit records | Missing files, failed activation, inconsistent old/new media references |
| CloudFront | Bytes, requests, cache efficiency where available, 4xx/5xx | Delivery error spike; unexpected transfer/request growth |
| Flutter | Crashlytics, Performance Monitoring, playback events | Crash regression, startup delay, buffering/playback failure regression |
| Product analytics | SQS ingestion, consumer lag, aggregate-table freshness and event validation | Analytics backlog, invalid-event spike or stale reports |
| Shared Grafana | EC2 CPU/RAM/disk, process health, dashboard query latency and backup status | Grafana unavailable, memory pressure, disk pressure or failed backup |
| Costs | AWS Budgets, Cost Explorer, cost-anomaly detection | Forecast or actual budget thresholds and unexpected service spending |
| Audit | CloudTrail, restricted admin audit trail, controlled SSM/session and host logs | Unexpected infrastructure, deployment or publishing changes |
Create three EVE dashboards in Grafana: application/database, media pipeline/delivery, and aggregated student playback experience. The same Grafana instance may contain separate folders and read-only data sources for the other approved AWS projects. Viewing-session telemetry needs implementation; existing CloudFront metrics cannot provide exact concurrency.
Grafana security and operation:
- Use read-only, least-privilege cross-account IAM roles for CloudWatch access.
- Put HTTPS in front of Grafana and restrict access by trusted IP, VPN or SSM tunnel. Never expose port
3000publicly. - Start with SQLite only for this small internal installation, and back up
/var/lib/grafanaplus configuration to a restricted S3 location. - Limit access to a few operations users, use 1–5 minute refresh intervals and avoid unnecessary plugins.
- Do not give Grafana unrestricted access to the production application database. Expose only aggregate reporting data through a restricted reporting user or API.
- Treat the single instance as recoverable, not highly available; Terraform and backups must be sufficient to rebuild it.
Keep ordinary logs approximately 14–30 days, with a deliberate longer audit retention policy. Sample successful traces; batch or sample mobile events. Never log passwords, tokens, full signed URLs, OTPs or personal student data. Avoid high-cardinality monitoring dimensions. Extra metrics, log ingestion, queries and detailed monitoring can incur charges.
Set alarm thresholds from observed baselines and service objectives rather than treating arbitrary percentages as capacity limits. Each alarm needs an owner and a short response runbook.
8. New database migration
- Confirm actual table/index size, nontransactional tables, growth and operational headroom before choosing new storage.
- SQL dump/import can target smaller allocated storage; snapshot restore cannot simply shrink the current 200 GiB allocation.
- Preserve identifiers, codes, comments, referrals, users and every required relationship.
- Rehearse export/import, integrity checks and application tests on a separate copy.
- Handle new registrations, comments and admin changes made after the initial backup. Define the cutover/write-freeze or replication approach explicitly.
- After the new database receives writes, rollback requires reconciliation; switching back blindly can lose data.
- Budget temporary overlap while old and new databases both exist. Do not delete the old database until acceptance and rollback-retention requirements are met.
9. Deployment and release gates
GitHub Actions should build and test versioned ARM64 application/worker artifacts and pinned Lambda container images, use OIDC for AWS access, and roll out through SSM, launch-template versions and Lambda image digests with health verification and rollback.
- No destructive live Git checkout as the normal deployment mechanism.
- Keep secrets outside repositories and release images.
- Keep app instances stateless: shared sessions where needed, durable files in S3 and scheduled work coordinated across instances.
- Bound PHP worker counts and database pools from measured memory and connection budgets.
- Account for temporary additional app capacity during safe rolling deployments; desired capacity one does not imply zero-downtime releases without extra capacity.
- Test old and new clients, QR routing, failed/partial uploads, retries, worker/Lambda failures, malformed and oversized media, DLQ redrive, heavy fallback and competing processing attempts.
- Test API and database capacity independently from CloudFront delivery.
- Prove backup restoration and an actionable rollback before cutover.
- Review
terraform planand reject any plan that creates, replaces or destroysevequalityor the existing media distribution. State-detachment guards preserve resources previously managed by older revisions. - Keep
media_manage_upload_cors = falseuntil the live bucket CORS document has been exported and merged. Enabling it transfers ownership of the complete CORS document to Terraform. - Preview legacy registration with
php artisan eve:import-legacy-hls; execute it only after bucket, CDN-host and sample-playback checks pass.
10. Cost controls and unresolved inputs
This is a resource/design document, not a current AWS price quote. Earlier conversational prices were point-in-time planning figures and must be rechecked before purchase.
- Pay for one normal app instance and conversion instance-hours actually required.
- ASG scale-to-zero terminates worker compute; retained disks, snapshots, images and logs can still cost money.
- Image, PDF and audio Lambdas use on-demand execution with no provisioned concurrency. SQS, S3, Lambda duration, temporary storage above the included amount and logs remain usage-based costs.
- The shared Grafana
t4g.micro, 10 GiB gp3 disk and public IPv4 are approximately ₹780/month before GST or ₹920/month including 18% GST, using an illustrative ₹90/USD exchange rate and current planning prices. CloudWatch usage is separate and prices must be rechecked before purchase. - Keep Grafana query refresh intervals controlled. Frequent CloudWatch API/log queries and excessive custom metrics can create charges even though Grafana OSS has no licence fee.
- Select CloudFront pricing using both transfer and request volume, account eligibility and compatibility requirements; HLS increases request counts.
- Avoid double-counting included CloudFront plan benefits, and separately price ALB/API protection and application logs.
- Keep new originals temporarily in
incoming/, delete them only after verified publication plus retention, and clean up processed versions only when proven inactive beyond rollback and active-viewing windows. - Decide networking before finalizing the bill: NAT, public IPv4, interface endpoints and cross-AZ transfer are not free substitutes.
- RDS backups, CloudWatch, WAF, CI runner minutes, operational buckets and migration overlap belong in the budget.
Still to measure or decide:
- Actual database/table sizes and growth; final new storage allocation.
- API latency, peak request load and PHP memory consumption; app ASG maximum.
- Largest source video, encoding benchmark, monthly conversion hours and acceptable queue delay.
- Image pixel/file limits, PDF size/page limits, audio duration limits, processor benchmarks and heavy-fallback thresholds.
- Supported runtime versions and ARM64 compatibility.
- CDN plan eligibility, complete media authorization and old-app delivery compatibility.
- Backup retention, recovery-time/data-loss objectives and acceptable maintenance downtime.
- Exact network egress design, alert thresholds and telemetry volumes.
- The exact definition of a valid view, analytics retention, report dimensions and privacy/access rules.
- Cross-account CloudWatch role boundaries for the five AWS projects and whether Grafana requires a fixed public IPv4 or private access only.
Implementation order: reliable authorized publication → isolated video/image/PDF/audio processing → controlled playback analytics → measured app/database sizing → CloudWatch plus shared Grafana monitoring → repeatable deployment → rehearsed migration and controlled cutover. Administrator/service security is required throughout; the accepted student login policy remains unchanged.